A Zend Framework tutorial, part two

by Naneau

In part one of my tutorial for a zend framework application I talked about creating a general design for your application. If you’re following my approach, you should by now have in your possession some kind of document with requirements for your application. You should also have a diagram with the basic layout of your underlying data structure.

In part one I described to you three classes that formed the basis of the application. There were classes for users, posts and reactions. Those are the models we will be working with. Let’s take a closer look.

1
2
3
4
5
6
<?php
require_once 'Zend/Db/Table.php';

class User extends Zend_Db_Table {
     protected $_dependentTables = array('Post', 'Reaction');
}

This tiny class describes our users. The only line of actual code tells Zend_Db_Table that there are other models (classes that extend Zend_Db_Table themselves) that depend on this one. In your diagram you should see this as some kind of connection between the entities, called a relation. For our application this means that users can have both posts and reactions.

1
2
Zend_Loader::loadClass('User');
$uM = new User();

Will create an object of the User class. The best way to look at this is as a gateway to your data. You can ask the object for specific rows, without having to write any SQL yourself. Say for instance that you want to find a user with the id 1. You could simply do the following:

1
2
3
4
$rowset = $uM->find(1);
if ($rowset->valid()) {
    $user = $rowset->current();
}

Note that the find() method returns an object of the class Zend_Db_Table_Rowset, even if you ask it to find a single id. If you have found a user row, you can do interesting things with it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$rowset = $uM->find(3);
//find the user(s) with id=3, will always return a rowset
if ($rowset->valid()) {
    //there is a user with id=3
   
    $user = $rowset->current();
    $user->username = 'Maurice';
    $user->save();
    //update the username
   
    $posts = $user->findDependentRowset('Post');
    //find all posts by this user
   
    foreach ($posts as $post) {
        //note that Zend_Db_Table_Rowset implements SPL Iterator
        //so you can use foreach()
        echo $post->title . ' ';
    }
}

Now that you can modify data, there’s two parts of your application left. The controllers and the views. Remember that requirements document from part one? Look at it again. You should see a list of things your application should be able to do. Controllers can do things. In our application you may want posts to be created, so your blog can get content. You may also want posts to be updated, deleted and read. These are all actions a controller can do.

If your applications are anything like mine, you’ll often come across a CRUD pattern. A simple controller for our posts would look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
require_once 'Zend/Controller/Action.php';

class PostController extends Zend_Controller_Action {
    public function createAction() {
    }
   
    public function readAction() {
    }
   
    public function updateAction() {
    }
   
    public function deleteAction() {
    }
}

As you can see, there’s an action function for each letter in CRUD. Because three of the actions work on a specific post, it could be handy to create a helper function:

1
2
3
4
5
6
7
8
9
10
11
12
13
private function getPost() {
    $id = (int) $this->getRequest()->getParam('id');
    //get the id out of the request, cast it to integer

    Zend_Loader::loadClass('Post');
    $mP = new Post();
    $rowset = $mP->find($id);
    if ($rowset->valid()) {
        return $rowset->current();
    }
    return false;
    //the post can't be found
}

Now you can access the requested post like:

1
2
3
4
5
6
if ($post = $this->getPost()) {
    //do something with it
}
else {
    //don't do something with it
}

I strongly believe in keeping my controller’s actions very simple. In my opinion they should only have a single function. I create multiple actions for handling a single form, one for displaying the form and checking whether received input is valid or not, and another to do whatever it is you needed a user’s input for. I also try to move most domain logic out of the controllers and into my models. In short, I try to make my controller files easy to understand and free from repetition.

You should be able to find all your functional requirements in a controller somewhere. Everything your application will be able to do is in there. In part three of this tutorial we’ll be talking about how we can access controllers with an http request.