zendframework/zend-db
Zend\Db is a database abstraction layer for PHP, offering SQL builders, adapters, platform-specific quoting, and result set utilities. It supports multiple drivers and helps you write portable, secure queries while keeping low-level control when you need it.
Start by installing the package via Composer: composer require zendframework/zend-db. Next, configure an Adapter—typically by providing a configuration array (or using Zend\Db\Adapter\Adapter::factory() with a DSN, credentials, and driver options). For immediate value, build a simple SELECT query using Zend\Db\Sql\Sql and execute it:
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
$adapter = new Adapter([
'driver' => 'Pdo_Mysql',
'hostname' => 'localhost',
'database' => 'test',
'username' => 'root',
'password' => '',
]);
$sql = new Sql($adapter);
$select = $sql->select()->from('users')->where(['id' => 1]);
$stmt = $select->prepareStatement();
$result = $stmt->execute()->current();
Consult the docs/ folder (if included) or the archived ZF2 docs—they remain accurate for usage despite the package’s archived status. The first real-world use case is often replacing raw PDO/MySQLi calls with portable query builders.
Sql::select() to build portable queries, then hydrate results into DTOs via Zend\Db\ResultSet\HydratingResultSet and a Zend\Hydrator (e.g., ArraySerializable or custom). This avoids magic arrays and ensures type safety.Adapter in a repository/service class to centralize DB access—e.g., getUserById($id) returns a hydrated user object, hiding SQL construction.Zend\Db\Sql\Platform\PlatformInterface (e.g., Zend\Db\Sql\Platform\MySQLPlatform) to inject vendor-specific behavior—like handling LIMIT/OFFSET in MySQL vs PostgreSQL—without conditional branching.Zend\Db\Metadata\Metadata to introspect tables/columns at runtime (e.g., for admin panels or migration scaffolding).Adapter::getDriver()->getConnection()->EVENT_AFTER_EXECUTE) to log queries or inject profiling hooks.laminas/laminas-db instead—it’s a drop-in replacement with identical API.where(['col' => $val]) auto-binds safely, avoid concatenating values (e.g., where("col = '$val'"))—it bypasses protection. Use where->expression() only with positional placeholders and bound params.RawExpression and careful vendor detection. Test across target DBs.Adapter instance per request—Adapter handles internal connection pooling and state. Avoid re-instantiating it in loops.Adapter::getDriver()->getConnection()->getDriverOptions()['profiling'] = true or use Zend\Db\Adapter\Platform\getSqlStringForQueryObject() to print final SQL strings.Zend\Db\Sql\Sql to add custom clauses (e.g., withCte()) or override Zend\Db\Sql\PreparableSqlEngine for non-standard query formatting.How can I help you explore Laravel packages today?