✅ 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
poststable and correspondingPostmodel. - Build a
PostTablewith CRUD operations. - Display posts in a new controller action.
