Zend Framework

Chapter 6: Working with Database and Models in Zend Framework 3

✅ Introduction

In modern web applications, data storage and retrieval is crucial. Zend Framework 3 (ZF3) provides multiple ways to interact with databases. The most common and recommended approach is to use the Zend\Db component, which offers a structured way to write queries, build models, and perform CRUD operations.

✅ Key Concepts

  • Zend\Db\Adapter: The database connection handler.
  • Zend\Db\TableGateway: A simple way to map tables to classes for CRUD operations.
  • Models: PHP classes representing business logic and data entities.
  • Service Manager: Injects database adapter into your models.

✅ Setting Up Database Adapter

Open module.config.php of your module and configure the database adapter in service_manager:


return [
    'service_manager' => [
        'factories' => [
            Zend\Db\Adapter\Adapter::class => Zend\Db\Adapter\AdapterServiceFactory::class,
        ],
    ],
];

Then, in your global.php or local.php config file:


return [
    'db' => [
        'driver'   => 'Pdo_Mysql',
        'database' => 'zf3_tutorial',
        'username' => 'root',
        'password' => '',
        'hostname' => 'localhost',
    ],
];

✅ Creating a Model

Let’s create a model class for a users table:


namespace Application\Model;

class User
{
    public $id;
    public $name;
    public $email;

    public function exchangeArray(array $data)
    {
        $this->id    = !empty($data['id']) ? $data['id'] : null;
        $this->name  = !empty($data['name']) ? $data['name'] : null;
        $this->email = !empty($data['email']) ? $data['email'] : null;
    }
}

✅ Using TableGateway

Now create a UserTable class that uses TableGateway:


namespace Application\Model;

use RuntimeException;
use Zend\Db\TableGateway\TableGatewayInterface;

class UserTable
{
    private $tableGateway;

    public function __construct(TableGatewayInterface $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }

    public function fetchAll()
    {
        return $this->tableGateway->select();
    }

    public function getUser($id)
    {
        $id = (int) $id;
        $rowset = $this->tableGateway->select(['id' => $id]);
        $row = $rowset->current();
        if (! $row) {
            throw new RuntimeException(sprintf(
                'Could not find user with id %d',
                $id
            ));
        }
        return $row;
    }

    public function saveUser(User $user)
    {
        $data = [
            'name'  => $user->name,
            'email' => $user->email,
        ];

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

        if ($id === 0) {
            $this->tableGateway->insert($data);
            return;
        }

        if (! $this->getUser($id)) {
            throw new RuntimeException(sprintf(
                'Cannot update user with id %d; does not exist',
                $id
            ));
        }

        $this->tableGateway->update($data, ['id' => $id]);
    }

    public function deleteUser($id)
    {
        $this->tableGateway->delete(['id' => (int) $id]);
    }
}

✅ Registering the Table in Module

Update Module.php of your module to register the service:


public function getServiceConfig()
{
    return [
        'factories' => [
            Model\UserTable::class => function($container) {
                $tableGateway = $container->get(Model\UserTableGateway::class);
                return new Model\UserTable($tableGateway);
            },
            Model\UserTableGateway::class => function ($container) {
                $dbAdapter = $container->get(AdapterInterface::class);
                $resultSetPrototype = new ResultSet();
                $resultSetPrototype->setArrayObjectPrototype(new Model\User());
                return new TableGateway('users', $dbAdapter, null, $resultSetPrototype);
            },
        ],
    ];
}

✅ Using the Model in a Controller

Finally, inject UserTable into a controller:


namespace Application\Controller;

use Application\Model\UserTable;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class UserController extends AbstractActionController
{
    private $table;

    public function __construct(UserTable $table)
    {
        $this->table = $table;
    }

    public function indexAction()
    {
        return new ViewModel([
            'users' => $this->table->fetchAll(),
        ]);
    }
}

✅ Best Practices

  • Always use prepared statements via TableGateway to avoid SQL injection.
  • Keep business logic in models, not in controllers.
  • Use ResultSet to map DB results to objects.

✅ Exercise

  • Create a posts table and corresponding Post model.
  • Build a PostTable with CRUD operations.
  • Display posts in a new controller action.

Leave a Reply

Your email address will not be published. Required fields are marked *