Zendframework 2 tutorial part 4

posted in: Zend Framework | 0

Summary:

8.Dealing with the Database (Models)

We have the User module set up with controller action methods and view scripts, Now it’s time to look at the model section of our application. We will make use of the Zend Framework class Zend\Db\TableGateway\TableGateway which is used to find, insert, update and delete rows from a database table.

We are going to use MySQL, via PHP’s PDO driver, so create a database called cruddb, and run these SQL statements to create the user table with some data in it.

CREATE TABLE user(

id int(11) NOT NULL auto_increment,

name varchar(100) NOT NULL,

petname varchar(100) NOT NULL,

PRIMARY KEY (id)

);

INSERT INTO user (name, petname)

VALUES  (‘venkat’,  ‘venky’);

INSERT INTO user (name, petname)

VALUES  (‘user1’,  ‘petuser1’);

INSERT INTO user (name, petname)

VALUES  (‘ user2’,  ‘petuser2’);

INSERT INTO user (name, petname)

VALUES  (‘user3’,  ‘petuser3’);

INSERT INTO user (name, petname)

VALUES  (‘user4’,  ‘petuser4’);

Now we have some data in a database and can write a very simple model for it.

9. Model File

Zend Framework does not provide a Zend\Model component because the model is your business logic and it’s up to you to decide how you want it to work.

For this project, we are going to create a very simple model by creating an UserTable class that uses the Zend\Db\TableGateway\TableGateway class in which each user object is an User object (known as an entity). This is an implementation of the Table Data Gateway design pattern to allow for interfacing with data in a database table

Let’s start by creating a file called User.php under module/User/src/User/Model:

<?php

namespace User\Model; 

class User

{

    public $id;

    public $name;

    public $petname;

 

    public function exchangeArray($data)

    {

        $this->id     = (!empty($data[‘id’])) ? $data[‘id’] : null;

        $this->name = (!empty($data[‘name’])) ? $data[‘name’] : null;

        $this->petname  = (!empty($data[‘petname’])) ? $data[‘petname’] : null;

    }

}

?>

Next, create our UserTable.php file in module/User/src/User/Model directory like this:

<?php

namespace User\Model;

 

use Zend\Db\TableGateway\TableGateway;

 

class UserTable

{

    protected $tableGateway;

 

    public function __construct(TableGateway $tableGateway)

    {

        $this->tableGateway = $tableGateway;

    }

 

    public function fetchAll()

    {

        $resultSet = $this->tableGateway->select();

        return $resultSet;

    }

 

    public function getUser($id)

    {

        $id  = (int) $id;

        $rowset = $this->tableGateway->select(array(‘id’ => $id));

        $row = $rowset->current();

        if (!$row) {

            throw new \Exception(“Could not find row $id”);

        }

        return $row;

    }

 

    public function saveUser(User $user)

    {

        $data = array(

            ‘name’ => $user->name,

            ‘petname’  => $user->petname,

        );

 

        $id = (int)$user->id;

        if ($id == 0) {

            $this->tableGateway->insert($data);

        } else {

            if ($this->getUser($id)) {

                $this->tableGateway->update($data, array(‘id’ => $id));

            } else {

                throw new \Exception(‘User id does not exist’);

            }

        }

    }

 

    public function deleteUser($id)

    {

        $this->tableGateway->delete(array(‘id’ => $id));

    }

}

?>

Firstly, we set the protected property $tableGateway to the TableGateway instance passed in the constructor. We will use this to perform operations on the database table for our users.

FetchAll():  retrieves all users rows from the database as a ResultSet,

getUser()   :    retrieves a single row as an User object,

saveUser() :   either creates a new row in the database or updates a row that already exists and

deleteUser(): removes the row completely.

The code for each of these methods is, hopefully, self-explanatory.

10.Using Service Manager to configure the table gateway and inject into the user table.

create a method called getServiceConfig() which is automatically called by the ModuleManager and applied to the ServiceManager. We’ll then be able to retrieve it in our controller when we need it.

To configure the ServiceManager, we can either supply the name of the class to be instantiated or a factory that instantiates the object when the ServiceManager needs it. We start by implementing getServiceConfig() to provide a factory that creates an UserTable. Add this method to the bottom of the Module.php file in module/User

// getAutoloaderConfig() and getConfig() methods here

// Add this method:

    public function getServiceConfig()

    {

        return array(

            ‘factories’ => array(

                ‘User\Model\UserTable’ =>  function($sm) {

                    $tableGateway = $sm->get(‘UserTableGateway’);

                    $table = new UserTable($tableGateway);

                    return $table;

                },

                ‘UserTableGateway’ => function ($sm) {

                    $dbAdapter = $sm->get(‘Zend\Db\Adapter\Adapter’);

                    $resultSetPrototype = new ResultSet();

                    $resultSetPrototype->setArrayObjectPrototype(new User());

                    return new TableGateway(‘user’, $dbAdapter, null,$resultSetPrototype);

                },

            ),

        );

    }

And add these lines at the top of the page after namespace

// Add these import statements:

use User\Model\User;

use User\Model\UserTable;

use Zend\Db\ResultSet\ResultSet;

use Zend\Db\TableGateway\TableGateway;

This method returns an array of factories that are all merged together by the ModuleManager before passing to the ServiceManager. The factory for User\Model\UserTable uses the ServiceManager to create an UserTableGateway to pass to the UserTable. We also tell the ServiceManager that an UserTableGateway is created by getting a Zend\Db\Adapter\Adapter (also from the ServiceManager) and using it to create a TableGateway object.

Finally, we need to configure the ServiceManager so that it knows how to get a Zend\Db\Adapter\Adapter. This is done using a factory called Zend\Db\Adapter\AdapterServiceFactory which we can configure within the merged config system. Zend Framework 2’s ModuleManager merges all the configuration from each module’s module.config.php file and then merges in the files in config/autoload (*.global.php and then *.local.php files). We’ll add our database configuration information to global.php

Modify config/autoload/global.php (in the Zendy Skeleton root ie.. zendy/config/autoload/global.php) with the following code:

<?php

return array(

    ‘db’ => array(

        ‘driver’         => ‘Pdo’,

        ‘dsn’            => ‘mysql:dbname=cruddb;host=localhost’,

        ‘username’ => ‘root’,
‘password’ => ”,
‘driver_options’ => array(

            PDO::MYSQL_ATTR_INIT_COMMAND => ‘SET NAMES \’UTF8\”

        ),

    ),

    ‘service_manager’ => array(

        ‘factories’ => array(

            ‘Zend\Db\Adapter\Adapter’

                    => ‘Zend\Db\Adapter\AdapterServiceFactory’,

        ),

    ),

);

?>

11.Back to the Controller:

Now that the ServiceManager can create an UserTable instance for us, we can add a method to the controller to retrieve it. Add getUserTable() to the UserController class:

Open the file: module/User/src/User/Controller/UserController.php:

    public function getUserTable()

    {

        if (!$this->userTable) {

            $sm = $this->getServiceLocator();

            $this-> userTable = $sm->get(‘User\Model\UserTable’);

        }

        return $this->userTable;

    }

And this line at the top of the class

protected $userTable;

Now we can  call getUserTable() from within our controller whenever we need to interact with our model.

If the service locator was configured correctly in Module.php, then we should get an instance of User\Model\UserTable when calling getUserTable()

Modify this indexAction in the UserController.php in the module/User/src/User/Controller with this code:

 public function indexAction()

    {

        return new ViewModel(array(

            ‘users’ => $this->getUserTable()->fetchAll(),

        ));

    }

Modify the index.phtml in the module/User/view/User/User/ with the following code :

<?php

$title = ‘Registered Users’;

$this->headTitle($title);

?>

<h1><?php echo $this->escapeHtml($title); ?></h1>

<p>

    <a href=”<?php echo $this->url(‘user’, array(‘action’=>’add’));?>”>Add new user</a>

</p>

<table class=”table”>

<tr>

    <th>Name</th>

    <th>PetName</th>

    <th>&nbsp;</th>

</tr>

<?php foreach ($users as $user) : ?>

<tr>

    <td><?php echo $this->escapeHtml($user->name);?></td>

    <td><?php echo $this->escapeHtml($user->petname);?></td>

    <td>

        <a href=”<?php echo $this->url(‘user’,

            array(‘action’=>’edit’, ‘id’ => $user->id));?>”>Edit</a>

        <a href=”<?php echo $this->url(‘user’,

            array(‘action’=>’delete’, ‘id’ => $user->id));?>”>Delete</a>

    </td>

</tr>

<?php endforeach; ?>

</table>

Finally Open your browser and type the url like this “zendy.local/user”
Then you will see the list of registered users.

Previous Post

Leave a Reply