Part 3: Creating the model, database and retrieving values from them – A not so quick quickstart to Zend Framework

1

Category : Programming

In the 3rd part of our series, we will now start implementing a user’s management system (as presented in part 2). We will use a MySQL database in our examples.

Setting up the database

Before starting, let’s create a database to be used in our system. To do that, go to MAMP’s start page and click on phpMyAdmin. You will see something like this:

And create a new database (i.e.: zfguide).

Since now we have a database, let’s define a set of user’s attributes, an create a table to store them.

1
2
3
4
5
6
7
8
9
10
11
12
create table users (
    id INT(11) not null auto_increment,
    name varchar(100) not null,
    email varchar(100) null,
    username varchar(50) not null unique,
    password varchar(50) not null,
    passwordStatus INT(2) DEFAULT 1,
    registrationStatus INT(2) DEFAULT 1,
    registrationDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    lastLogin TIMESTAMP null,
    primary key (id)
) type=InnoDB;

Basically we will have some basic attributes, like id, name, email, username, password, registration date and last login, and also some other attributes we will use to control users’ status, like password status and registration status.

The passwordStatus represents the current status of the password value in the password column. If passwordStatus is ’0′ it will be a temporary password, if it is ’1′, it will be a definitive password. The registrationStatus represents user’s registration status. If registrationStatus is ’0′, the user is inactive, if it is ’1′ the user is active, and if it is ’2′, user’s registration is in a “waiting confirmation” status.

Now, let’s create a folder to store our .sql files. We recommend to create a folder in the root of your project and call it “sources”. This folder can be also used to store other modeling files, like UML diagrams, etc. Inside the sources folder, create a db folder. Inside “db” folder, create a file called “users-create.sql” and insert the create table statement there.

Now, let’s create a sql file (users-populate.sql) to populate this table:

1
2
3
INSERT INTO users (`name`,`email`,`username`,`password`,`passwordStatus`,`registrationStatus`,`registrationDate`,`lastLogin`) VALUES('john','john@johnsemail.com','john','d4cff13ae8937aca8a937253a6140192587f3c3de640',1,1,now(),now());
INSERT INTO users (`name`,`email`,`username`,`password`,`passwordStatus`,`registrationStatus`,`registrationDate`,`lastLogin`) VALUES('alice','alice@aliceemail.com','alice','d4cff13ae8937aca8a937253a6140192587f3c3de640',1,1,now(),now());
INSERT INTO users (`name`,`email`,`username`,`password`,`passwordStatus`,`registrationStatus`,`registrationDate`,`lastLogin`) VALUES('anna','anna@annaemail.com','anna','d4cff13ae8937aca8a937253a6140192587f3c3de640',1,1,now(),now());

Now go to phpMyAdmin, create the table and use those insert statements to insert the register into the table.

Creating the model using Zend Framework

Now we have to update our configuration file and create the classes to connect to the database. We can use the zf tool to help us on this task. So, open a terminal, go to the project’s root folder and type:

1
zf configure db-adapter 'adapter=PDO_MYSQL&dbname=zfguide&host=localhost&username=root&password=root'

This first command (above), automatically edits the configuration file and adds database connection information that will be used by our application.

1
zf create db-table Users users

This command takes two arguments, the name  you want to refer to the class, and the database table it will map to. At the end of its execution, the zf tool generates Users.php in application/models/DbTable/ that represents the table “users” that we have created in the database.

This class is very simple. It has only the class declaration and a protected attribute to indicate the database table’s name. So, the class is like this:

1
2
3
4
5
<?php
class Application_Model_DbTable_Users extends Zend_Db_Table_Abstract
{
    protected $_name = 'users';
}

However,  we recommend to make use of some class constants in order to make future changes easier, specially when we rename a column or something like it. Basically, what we are going to do is to create one class constant for each table column (using a prefix “COL_” ), and for columns which values are a range of pre-defined values, we will also create constants to defines these values (using a prefix “ENUM_”). So, after inserting the constants, the Application_Model_DbTable_Users class will have the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php

class Application_Model_DbTable_Users extends Zend_Db_Table_Abstract
{

    const NAME = "users";
   
    const COL_ID = "id";
    const COL_NAME = "name";
    const COL_EMAIL = "email";
    const COL_USERNAME = "username";   
    const COL_PASSWORD = "password";   
    const COL_PASSWORD_STATUS = "passwordStatus";
    const COL_REGISTRATION_DATE = "registrationDate";
    const COL_REGISTRATION_STATUS = "registrationStatus";
    const COL_LAST_LOGIN = "lastLogin";
   
    const ENUM_PASSWORD_STATUS_DEFINITIVE = 1;
    const ENUM_PASSWORD_STATUS_TEMPORARY = 0;
   
    const ENUM_REGISTRATION_STATUS_ACTIVE = 1;
    const ENUM_REGISTRATION_STATUS_INACTIVE = 0;
    const ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION = 2;
       
    protected $_name = self::NAME;
    protected $_primary = self::COL_ID;

}

Now we have a class that represents users’ db table. The next step is to create a Model object which will represent a User to the application. To create the model, go to the terminal and type:

1
zf create model User

The zf tool will create the User.php file and the class declaration inside the file. Now we have to create the class’ methods (basically, getters and setters) manually. Here is the User.php final code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php

class Application_Model_User
{
   
    protected $_id;
    protected $_name;
    protected $_email;
    protected $_username;
    protected $_password;
    protected $_passwordStatus;
    protected $_registrationDate;
    protected $_registrationStatus;
    protected $_lastLogin;

    const ENUM_REGISTRATION_STATUS_INACTIVE = 0;
    const ENUM_REGISTRATION_STATUS_ACTIVE = 1; 
    const ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION = 2;
   
    const ENUM_PASSWORD_STATUS_TEMPORARY = 0;
    const ENUM_PASSWORD_STATUS_DEFINITIVE = 1;         
   
    public function __construct(array $attributes = null)
    {
        // initialize Zend_Date objects
        $this->_registrationDate = new Zend_Date();
        $this->_lastLogin = new Zend_Date();
       
        if (is_array($attributes)) {
            $this->setAttributes($attributes);
        }        
       
    }

    public function setAttributes(array $attributes)
    {
        $methods = get_class_methods($this);
        foreach ($attributes as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }    
    }
   
    public function setId($id)
    {
        $this->_id = (int) $id;
        return $this;
    }

    public function getId()
    {
        return $this->_id;
    }
   
    public function setName($text)
    {
        $this->_name = (string) $text;
        return $this;
    }

    public function getName()
    {
        return $this->_name;
    }
   
    public function setEmail($text)
    {
        $this->_email = (string) $text;
        return $this;
    }

    public function getEmail()
    {
        return $this->_email;
    }
   
    public function setUsername($text)
    {
        $this->_username = (string) $text;
        return $this;
    }

    public function getUsername()
    {
        return $this->_username;
    }

    public function setPassword($text)
    {
        $this->_password = (string) $text;
        return $this;
    }

    public function getPassword()
    {
        return $this->_password;
    }
       
    public function getPasswordStatus()
    {
        return $this->_passwordStatus;
    }    
   
    public function setPasswordStatus($status)
    {
        if ( ($status != self::ENUM_PASSWORD_STATUS_DEFINITIVE) && ($status != self::ENUM_PASSWORD_STATUS_TEMPORARY) )
            throw new Zend_Exception('Invalid Password Status');
        $this->_passwordStatus = $status;
        return $this;          
    }

    public function getRegistrationStatus()
    {
        return $this->_registrationStatus;
    }    
   
    public function setRegistrationStatus($status)
    {
        if ( ($status != self::ENUM_REGISTRATION_STATUS_INACTIVE) && ($status != self::ENUM_REGISTRATION_STATUS_ACTIVE) && ($status != self::ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION))
            throw new Zend_Exception('Invalid Registration Status');
        $this->_registrationStatus = $status;
        return $this;          
    }
   
    public function setRegistrationDate(Zend_Date $date)
    {
        $this->_registrationDate = $date;
        return $this;          
    }
   
    public function getRegistrationDate()
    {
        return $this->_registrationDate;
    }
       
    public function setLastLogin(Zend_Date $date)
    {
        $this->_lastLogin = $date;
        return $this;          
    }

    public function getLastLogin()
    {
        return $this->_lastLogin;
    }
   
}

The last class of our model, is a class the implements a dataMapper (see dataMapper) to isolate the application from the database and vice-versa. Thus, this data mapper will stay in the middle between the application and the database and will map the desired actions between them.

In our application, we will need the mapper to have the following actions:

  • save – to save a user to the database
  • findById – to find a user using user’s id
  • fetchAll – to fetch all registries from the table
  • delete – to delete a specific user

To create the mapper, go to the terminal and type:

1
zf create model UsersMapper

Now we will manually implement the methods described above. We will also implement some auxiliary methods to make the mapping between the database and model easier. The UsersMapper class should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
class Application_Model_UsersMapper
{

    protected $_dbTable;

    public function __construct() {
        $this->_dbTable = new Application_Model_DbTable_Users();
    }
   
    public function save(Application_Model_User $user)
    {      
        $data = self::mapToDbDataArray($user);
       
        if (null === ($id = $user->getId())) {
            $id = $this->_dbTable->insert($data);
        } else {
            $this->_dbTable->update($data, array(Application_Model_DbTable_Users::COL_ID . ' = ?' => $id));
        }

        return $id;
    }

    public function findById($id)
    {
        $result = $this->_dbTable->find($id);
        if (0 == count($result)) {
            return;
        }
        $row = $result->current();
       
        return self::mapToModelObject($row);
    }


    public function fetchAll()
    {
        $resultSet = $this->_dbTable->fetchAll();
        $entries   = array();
        foreach ($resultSet as $row) {
            $entries[] = self::mapToModelObject($row);
        }
       
        return $entries;
    }

    public function delete($id)
    {
        $where = $this->_dbTable->getAdapter()->quoteInto(Application_Model_DbTable_Users::COL_ID . ' = ?', $id);
        return $this->_dbTable->delete($where);
    }
   
    protected static function mapToModelObject(Zend_Db_Table_Row_Abstract $row)
    {
        $user = new Application_Model_User();
                       
        switch ($row->{Application_Model_DbTable_Users::COL_PASSWORD_STATUS}) {
            case Application_Model_DbTable_Users::ENUM_PASSWORD_STATUS_TEMPORARY:
                $pwStatus = Application_Model_User::ENUM_PASSWORD_STATUS_TEMPORARY;
                break;
            case Application_Model_DbTable_Users::ENUM_PASSWORD_STATUS_DEFINITIVE:
                $pwStatus = Application_Model_User::ENUM_PASSWORD_STATUS_DEFINITIVE;
                break;
            default:
                $pwStatus = Application_Model_User::ENUM_PASSWORD_STATUS_DEFINITIVE;
        }
       
        switch ($row->{Application_Model_DbTable_Users::COL_REGISTRATION_STATUS}) {
            case Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_INACTIVE:
                $regStatus = Application_Model_User::ENUM_REGISTRATION_STATUS_INACTIVE;
                break;
            case Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_ACTIVE:
                $regStatus = Application_Model_User::ENUM_REGISTRATION_STATUS_ACTIVE;
                break;
            case Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION:
                $regStatus = Application_Model_User::ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION;
                break;
            default:
                $regStatus = Application_Model_User::ENUM_REGISTRATION_STATUS_INACTIVE;
        }
       
        $user->setId($row->{Application_Model_DbTable_Users::COL_ID})
                ->setName($row->{Application_Model_DbTable_Users::COL_NAME})
                ->setEmail($row->{Application_Model_DbTable_Users::COL_EMAIL})
                ->setUsername($row->{Application_Model_DbTable_Users::COL_USERNAME})
                ->setPassword($row->{Application_Model_DbTable_Users::COL_PASSWORD})
                ->setPasswordStatus($pwStatus)
                ->setRegistrationStatus($regStatus)
                ->setRegistrationDate(new Zend_Date($row->{Application_Model_DbTable_Users::COL_REGISTRATION_DATE}, Zend_Date::ISO_8601))
                ->setLastLogin(new Zend_Date($row->{Application_Model_DbTable_Users::COL_LAST_LOGIN}, Zend_Date::ISO_8601));
        return $user;
    }  

    protected static function mapToDbDataArray(Application_Model_User $user)
    {
        $data = array(
            Application_Model_DbTable_Users::COL_NAME => $user->getName(),
            Application_Model_DbTable_Users::COL_EMAIL => $user->getEmail(),
            Application_Model_DbTable_Users::COL_USERNAME => $user->getUsername(),                                    
            Application_Model_DbTable_Users::COL_PASSWORD => $user->getPassword(),            
            Application_Model_DbTable_Users::COL_REGISTRATION_DATE => $user->getRegistrationDate()->toString(Zend_Date::ISO_8601),            
            Application_Model_DbTable_Users::COL_LAST_LOGIN => $user->getLastLogin()->toString(Zend_Date::ISO_8601)          
        );
   
        switch ($user->getPasswordStatus()) {
            case Application_Model_User::ENUM_PASSWORD_STATUS_TEMPORARY:
                $data[Application_Model_DbTable_Users::COL_PASSWORD_STATUS] = Application_Model_DbTable_Users::ENUM_PASSWORD_STATUS_TEMPORARY;
                break;
            case Application_Model_User::ENUM_PASSWORD_STATUS_DEFINITIVE:
                $data[Application_Model_DbTable_Users::COL_PASSWORD_STATUS] = Application_Model_DbTable_Users::ENUM_PASSWORD_STATUS_DEFINITIVE;
                break;
            default:
                $data[Application_Model_DbTable_Users::COL_PASSWORD_STATUS] = Application_Model_DbTable_Users::ENUM_PASSWORD_STATUS_DEFINITIVE;
        }
       
        switch ($user->getRegistrationStatus()) {
            case Application_Model_User::ENUM_REGISTRATION_STATUS_INACTIVE:
                $data[Application_Model_DbTable_Users::COL_REGISTRATION_STATUS] = Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_INACTIVE;
                break;
            case Application_Model_User::ENUM_REGISTRATION_STATUS_ACTIVE:
                $data[Application_Model_DbTable_Users::COL_REGISTRATION_STATUS] = Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_ACTIVE;
                break;
            case Application_Model_User::ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION:
                $data[Application_Model_DbTable_Users::COL_REGISTRATION_STATUS] = Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_WAITING_CONFIRMATION;
                break;
            default:
                $data[Application_Model_DbTable_Users::COL_REGISTRATION_STATUS] = Application_Model_DbTable_Users::ENUM_REGISTRATION_STATUS_INACTIVE;
        }
       
        return $data;
    }

}

Now our model classes are ready. Let’s proceed with the Controller.

Setting Up the Controller

To create a controller, let’s use the zf tool. Open a terminal, go to your project’s root and type:

1
zf create controller Users

This will create a new controller called UsersController (application/controllers/UsersController.php) and also a view script for the controller (application/views/scripts/users/index.phtml).

Now let’s open the UsersController and insert some code into the indexAction function. We will  use this function to list all the Users entries in the database. To do that, we will use the mapper we have created. Look at the source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

class UsersController extends Zend_Controller_Action
{

    public function init()
    {
        /* Initialize action controller here */
    }

    public function indexAction()
    {
        $usersMapper = new Application_Model_UsersMapper();
        $this->view->users = $usersMapper->fetchAll();
    }


}

Basically what we have done was to get the database entries and send it to the view. Now we will retrieve this values in the view and print them in the screen. So, open application/views/scripts/guestbook/index.phtml and insert the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Registered Users: <br />
<table>
    <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Login</th>
        <th>Registration Date</th>
        <th>Last Login</th>
    </tr>  
    <?php foreach ($this->users as $user): ?>
    <tr>
        <td>       
            <?php echo $this->escape($user->getName()); ?>
        </td>
        <td>       
            <?php echo $this->escape($user->getEmail()); ?>
        </td>
        <td>       
            <?php echo $this->escape($user->getUsername()); ?>
        </td>
        <td>
            <?php echo $this->escape($user->getRegistrationDate()); ?>
        </td>
        <td>
            <?php echo $this->escape($user->getLastLogin()); ?>
        </td>
    </tr>
    <?php endforeach; ?>
</table>

Now browse to http://zfguide/users and check the results.

Improving the listing: adding pagination support

An interesting class from Zend Framework library is the Zend_Paginator. This class make pagination easy and also offer controls, which are different ways to display the page numbers. Since we are listing the registered users in our index action, let’s also insert pagination in this list.

First of all, Zend_Paginator requires a parameter in its constructor method. This parameter can be an array, a DbSelect (Zend_Db_Select object), a Zend_Db_Table_Select or an Iterator instance. We will use the Zend_Db_Table_Select. However we cannot expose our Zend_Db_Table_Users to the controller, so the best way to do this is to create a new method int the UsersMapper that will return a paginator object to the controller. Basically, the getPaginator function will return a instance of Zend_Paginator that is ready to be used.

1
2
3
4
5
6
7
8
9
public static function getPaginator()  
    {  
        $userTable = new Application_Model_DbTable_Users();  
        $paginator = Zend_Paginator::factory($userTable->select());  
        $paginator->setFilter(new Zend_Filter_Callback(  
            array('Application_Model_UsersMapper', 'mapToUserModel'))  
        );    
        return $paginator;  
    }

Another important feature of Zend_Paginator is the setFilter method. This method allows you to load data from the row object and convert it to any model object you want. In the setFilter, we instantiate the Zend_Filter_Callback and pass the class and the method names of the method that will be called. Thus, now we have to create the mapToUserModel function, which will be called. The code is very simple:

1
2
3
4
5
6
7
public static function mapToUserModel(Zend_Db_Table_Rowset_Abstract $rows) {       
        $entries   = array();
        foreach ($rows as $row) {          
            $entries[] = Application_Model_UsersMapper::mapToModelObject($row);
        }
        return $entries;
    }

Now we are done with the Zend_Mapper in this part of the tutorial. Let’s open the UsersController to make use of the paginator we created. We only have to initiate the paginator, set the maximum number of items we are going to display on each page and set the current page number. Here is the source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

class UsersController extends Zend_Controller_Action
{

    public function init()
    {
        /* Initialize action controller here */
    }

    public function indexAction()
    {
        $paginator = Application_Model_UsersMapper::getPaginator();        
        $paginator->setItemCountPerPage(15);
        $paginator->setCurrentPageNumber($this->_getParam('page'));
                                               
        // send paginator to the view
        $this->view->paginator = $paginator;
    }

}

To display the page number we will make use of a new helper, called PaginationControl. This helper accepts up to four parameters: the paginator instance, a scrolling style, a view partial, and an array of additional parameters. The second parameter defines the control style, and the third, defines a file that controls how the pagination should look. We will use the Sliding style, which is a Yahoo!-like scrolling style that positions the current page number in the center of the page range (you can check the other styles here).

Let’s create the file pagination_control.phtml. This file should be in the application/views/scripts folder and this is the source code (you can find more details about the functions used in this file here):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php if ($this->pageCount): ?>
<div class="paginationControl">
   
    <!-- First page link -->
    <?php if ($this->first != $this->current): ?>
        <a href="<?php echo $this->url(array('page' => $this->first)); ?>">&lt;&lt; First</a>&nbsp;&nbsp;
    <?php elseif(($this->first == $this->current) && ($this->pageCount > 1)): ?>
        <span class="disabled">&lt;&lt; First</span>&nbsp;&nbsp;
    <?php endif; ?>
   
    <!-- Previous page link -->
    <?php if (isset($this->previous)): ?>
        <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">&lt; Previous</a>&nbsp;
    <?php elseif(!isset($this->previous) && ($this->pageCount > 1)): ?>
        <span class="disabled">&lt; Previous</span>&nbsp;
    <?php endif; ?>

    <!-- Numbered page links -->
    <?php foreach ($this->pagesInRange as $page): ?>
        <?php if ($page != $this->current): ?>
            <a href="<?php echo $this->url(array('page' => $page)); ?>"><?php echo $page; ?></a>&nbsp;
        <?php elseif(($page == $this->current) && ($this->pageCount > 1)): ?>
            <?php echo $page; ?>&nbsp;
        <?php endif; ?>
    <?php endforeach; ?>

    <!-- Next page link -->
    <?php if (isset($this->next)): ?>
        <a href="<?php echo $this->url(array('page' => $this->next)); ?>">Next &gt;</a>&nbsp;
    <?php elseif(!isset($this->next) && ($this->pageCount>1)): ?>
        <span class="disabled">Next &gt;</span>&nbsp;
    <?php endif; ?>

    <!-- Last page link -->
    <?php if ($this->pageCount != $this->current): ?>
        <a href="<?php echo $this->url(array('page' => $this->pageCount)); ?>">Last &gt;&gt;</a>&nbsp;
    <?php elseif (($this->pageCount == $this->current) && ($this->pageCount > 1)): ?>
        <span class="disabled">Last &gt;&gt; </span>&nbsp;
    <?php endif; ?>

</div>
<?php endif; ?>

To conclude, let’s edit the index.phtml file, and change it to make use of paginator and the paginator control. We will use the paginator in the “foreach” loop. The paginator control will be added at the end a we also added a description before the table, wich shows the total number of registries and page number. Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Registered Users: <br />
<p><?php echo $this->paginator->getTotalItemCount() . " registers. Showing page " . $this->paginator->getCurrentPageNumber() . " of " . $this->paginator->count(); ?></p>

<?php if (count($this->paginator)): ?>
    <table>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Login</th>
            <th>Registration Date</th>
            <th>Last Login</th>
        </tr>  
        <?php foreach ($this->paginator as $user): ?>
        <tr>
            <td>       
                <?php echo $this->escape($user->getName()); ?>
            </td>
            <td>       
                <?php echo $this->escape($user->getEmail()); ?>
            </td>
            <td>       
                <?php echo $this->escape($user->getUsername()); ?>
            </td>
            <td>
                <?php echo $this->escape($user->getRegistrationDate()); ?>
            </td>
            <td>
                <?php echo $this->escape($user->getLastLogin()); ?>
            </td>
        </tr>
        <?php endforeach; ?>
    </table>
<?php endif; ?>

<?php echo $this->paginationControl($this->paginator, 'Sliding', 'pagination_control.phtml'); ?>

And that’s it.

In the part 4 of this series, we will describe how to create and make use of Zend_Forms and also show how to save them into the database.

Popularity: 35% [?]