Package · cdo

CDO

CDO (Connection Data Object) is an extended PDO wrapper for PHP. It gives you safe, parameterised DML — insert, update, delete, upsert and their batch variants — a type-aware binder that picks the right PDO::PARAM_* for every value, and Qb, a composable query builder that produces injection-safe WHERE fragments. It speaks PostgreSQL, MySQL/MariaDB and Oracle, and adapts its SQL to each.

Philosophy

  • Parameterised by default — every value goes through a named placeholder and a typed bind. There is no string interpolation of values anywhere in the DML path, so injection is not a risk you have to remember to avoid.
  • Driver-aware, not driver-locked — CDO detects PostgreSQL, MySQL, MariaDB and Oracle at connect time and rewrites RETURNING, ON CONFLICT vs ON DUPLICATE KEY UPDATE, and timezone handling for you.
  • Thin over PDOCDO extends PDO, so every method you already know (query, prepare, fetchAll, transactions) is still there. The wrapper only adds convenience on top; it never takes PDO away.

Core concepts

  • CDO — the connection. Extends PDO and adds insert, insertGroup, upsert, upsertGroup, update, delete.
  • Qb — an immutable query builder. Static factories (Qb::eq, Qb::and, …) return composable fragments, each carrying its own bound values.
  • CDOBind — a name + value pair. Auto-created by Qb; you build one by hand to name a placeholder or reuse it across conditions.
  • Config classes — extend PgDbConfig / MySqlDbConfig (or use the inline PgDbCall / MySqlDbCall / DbCall) to describe a connection.
  • ConnectionPool — a process-level registry that instantiates each config once and hands back a ready CDO.

Key features

  • Full CRUD + upsert — single-row and chunked batch inserts and upserts, with automatic primary-key return where the driver supports RETURNING.
  • Composable Qb — comparison, NULL, set, pattern, range, logical, CASE and raw operators, all combinable with and / or / xor / clip.
  • Type-aware bindingnull, bool, int, array (JSON), objects (JsonSerializable, Stringable, DateTimeInterface, BackedEnum) are each bound with the correct PDO type.
  • Health checksping() and pingDetail() (status + latency) on every config, plus lazy connect / disconnect / reconnect.
  • PSR-3 logging — attach any LoggerInterface; every generated query is logged at debug level.

Good fit for

Application data access where you want parameterised safety and batch throughput without the weight of a full ORM — services, workers, importers, and anywhere you already reach for PDO but keep re-writing the same insert/upsert plumbing.

Requirements

  • PHP ≥ 8.3
  • ext-pdo and the driver extension for your database (pdo_pgsql, pdo_mysql, or pdo_oci)
  • psr/log ^3.0

See Installation & requirements for the full list.

Install

bash
composer require flytachi/winter-cdo

Quick taste

Get a connection, insert a row, read the generated id:

php
use Flytachi\Winter\Cdo\ConnectionPool;
use Flytachi\Winter\Cdo\Qb;

$cdo = ConnectionPool::db(AppDb::class);

$id = $cdo->insert('users', ['name' => 'Alice', 'email' => 'alice@example.com']);

$cdo->update('users', ['name' => 'Alice Smith'], Qb::eq('id', $id));

Walk through it end to end in the Quickstart.

Continue with Installation & requirements, the Quickstart, and the Mental model.