class ZtdPdo
    extends PDO
Public API: explicitly declared with @visibility public.

PDO proxy that enforces ZTD behavior for reads and writes.

Uses delegation pattern: extends PDO for type compatibility, but delegates all operations to an inner PDO instance when using fromPdo().

Supports multiple database platforms via SessionFactory injection or auto-detection:

  • MySQL (k-kinzal/ztd-query-mysql)
  • PostgreSQL (k-kinzal/ztd-query-postgres)
  • SQLite (k-kinzal/ztd-query-sqlite)
Simulate a write without changing the physical tabledoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->exec("INSERT INTO users VALUES (1, 'Alice')") // => 1
    $pdo->query('SELECT name FROM users')->fetchColumn() // => 'Alice'
    $native->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 0

Methods§

public function __construct(
    string $dsn,
    ?string $username = null,
    ?string $password = null,
    array<int, mixed>|null $options = null,
    ZtdConfig|null $config = null,
    SessionFactory|null $factory = null,
)
Public API: explicitly declared with @visibility public.

Configure a new ZTD-enabled PDO wrapper.

If $factory is provided, it is used directly to create the session. If $factory is null, the factory is auto-detected from the PDO driver name.

Parameters

$dsnstring
$username?string
$password?string
$optionsarray<int, mixed>|nullDriver options, as PDO::__construct() takes them
$configZtdConfig|nullHow ZTD is to behave, or null for the default
$factorySessionFactory|nullPlatform to rewrite with, or null to read it off the driver

Throws

RuntimeException When the driver has no platform package installed
Open a ZTD connectiondoctest
$pdo = new \ZtdQuery\Adapter\Pdo\ZtdPdo('sqlite::memory:');
    $pdo->isZtdEnabled() // => true
Calls 3
public static function fromPdo(
    PDO $pdo,
    ZtdConfig|null $config = null,
    SessionFactory|null $factory = null,
): static
Public API: explicitly declared with @visibility public.

Create a ZtdPdo wrapper around an existing PDO instance.

This allows reusing an existing PDO connection instead of creating a new one. The wrapped PDO instance will be used for all database operations.

If $factory is provided, it is used directly to create the session. If $factory is null, the factory is auto-detected from the PDO driver name.

Parameters

$pdoPDOConnection to wrap
$configZtdConfig|nullHow ZTD is to behave, or null for the default
$factorySessionFactory|nullPlatform to rewrite with, or null to read it off the driver

Returns

static The connection, with ZTD in front of it

Throws

RuntimeException When the driver has no platform package installed
Wrap an existing PDO connectiondoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->isZtdEnabled() // => true
    $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) // => 'sqlite'
Test cases 333
Called from 1
Calls 4
public function enableZtd(): void
Public API: explicitly declared with @visibility public.

Enable ZTD mode for this connection.

While it is enabled, nothing this connection is asked to write reaches the database; reads are answered from the shadow instead.

Resume shadowing after native accessdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->disableZtd();
    $pdo->enableZtd();
    $pdo->isZtdEnabled() // => true
Calls 1
public function disableZtd(): void
Public API: explicitly declared with @visibility public.

Disable ZTD mode for this connection.

Once it is disabled, statements run against the database as they were written, and the shadow is not consulted.

Temporarily pass queries through to the databasedoctest
$pdo = new \ZtdQuery\Adapter\Pdo\ZtdPdo('sqlite::memory:');
    $pdo->disableZtd();
    $pdo->isZtdEnabled() // => false
    $pdo->enableZtd();
    $pdo->isZtdEnabled() // => true
Calls 1
public function isZtdEnabled(): bool
Public API: explicitly declared with @visibility public.

Check whether ZTD mode is enabled.

Returns

bool Whether writes are being shadowed rather than carried out
Inspect shadowing statedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->isZtdEnabled() // => true
Test cases 2
Calls 1
public function prepare(string $query, array<mixed> $options = []): PDOStatement|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$querystring
$optionsarray<mixed>Driver options, as PDO::prepare() takes them

Returns

PDOStatement|false The prepared statement, or false where the driver would not prepare one

Throws

ZtdPdoException When ZTD cannot carry the statement out, or an option is one PDO cannot be given
Bind values to a simulated INSERTdoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $statement = $pdo->prepare('INSERT INTO users VALUES (:id, :name)');
    $statement->execute(['id' => 1, 'name' => 'Alice']) // => true
    $statement->rowCount() // => 1
    $native->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 0
Test cases 1
Called from 1
Calls 2
public function query(
    string $query,
    ?int $fetchMode = null,
    mixed ...$fetchModeArgs,
): PDOStatement|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$querystring
$fetchMode?int
$fetchModeArgsmixedThe rest of what the fetch mode reads

Returns

PDOStatement|false The executed statement, or false where it did not run

Throws

ZtdPdoException When ZTD cannot carry the statement out
Read virtual rowsdoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->exec("INSERT INTO users VALUES (1, 'Ada')");
    $pdo->query('SELECT name FROM users')->fetchColumn() // => 'Ada'
    $native->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 0
Test cases 1
Calls 2
public function exec(string $statement): int|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

A batch is carried out one statement at a time, and stops at the first one that does not run; what it answers is what the last one that ran affected, which is what PDO answers for a batch.

Parameters

$statementstring

Returns

int|false Rows the statement affected, or false where it did not run

Throws

ZtdPdoException When ZTD cannot carry the statement out
Count simulated mutationsdoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->exec("INSERT INTO users VALUES (1, 'Ada')") // => 1
    $pdo->exec("UPDATE users SET name = 'Grace'") // => 1
    $native->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 0
Test cases 1
Called from 1
Calls 2
public static function connect(
    string $dsn,
    ?string $username = null,
    ?string $password = null,
    array<mixed>|null $options = null,
): static
Public API: explicitly declared with @visibility public.

{@inheritDoc}

The connection is opened with PDO's constructor rather than with PDO::connect(), which exists only from PHP 8.4 on while this package supports 8.1. What connect() adds is a driver-specific subclass of PDO, and nothing here asks the wrapped connection for anything a subclass would answer differently.

This carries no #[\Override] for the same reason: from PHP 8.3 on the attribute is checked, and on 8.1 through 8.3 there is no PDO::connect() for it to be checked against.

Parameters

$dsnstring
$username?string
$password?string
$optionsarray<mixed>|nullDriver options, as PDO::connect() takes them

Returns

static The new connection, with ZTD in front of it

Throws

RuntimeException When the driver has no platform package installed
Create a connection through the static factorydoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::connect('sqlite::memory:');
    $pdo->isZtdEnabled() // => true
Test cases 1
Calls 2
public function beginTransaction(): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool
Begin a transaction for native and shadow statedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->beginTransaction() // => true
    $pdo->inTransaction() // => true
    $pdo->rollBack();
Calls 1
public function commit(): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool
Keep committed virtual writesdoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->beginTransaction();
    $pdo->exec("INSERT INTO users VALUES (1, 'Ada')");
    $pdo->commit() // => true
    $pdo->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 1
    $native->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 0
Calls 1
public function rollBack(): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool
Undo virtual writes in a transactiondoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->beginTransaction();
    $pdo->exec("INSERT INTO users VALUES (1, 'Ada')");
    $pdo->rollBack() // => true
    $pdo->query('SELECT COUNT(*) FROM users')->fetchColumn() // => 0
Calls 1
public function inTransaction(): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool
Observe transaction statedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->inTransaction() // => false
    $pdo->beginTransaction();
    $pdo->inTransaction() // => true
    $pdo->rollBack();
Calls 1
public function lastInsertId(?string $name = null): string|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$name?string

Returns

string|false
Read a generated shadow keydoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->exec("INSERT INTO users (name) VALUES ('Ada')");
    $pdo->lastInsertId() // => '1'
Calls 1
public function errorCode(): ?string
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

?string
Read a native SQLSTATEdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->disableZtd();
    $pdo->query('SELECT 1');
    $pdo->errorCode() // => '00000'
Calls 1
public function errorInfo(): array{0: string|null, 1: int|null, 2: string|null}
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

array{0: string|null, 1: int|null, 2: string|null}
Read native error informationdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->disableZtd();
    $pdo->query('SELECT 1');
    $pdo->errorInfo()[0] // => '00000'
Calls 1
public function getAttribute(int $attribute): mixed
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$attributeint

Returns

mixed
Read the underlying driver namedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) // => 'sqlite'
Calls 1
public function setAttribute(int $attribute, mixed $value): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$attributeint
$valuemixed

Returns

bool
Set the default fetch modedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC) // => true
    $pdo->query('SELECT 7 AS id')->fetch() // => ['id' => 7]
Calls 1
public function quote(string $string, int $type = PDO::PARAM_STR): string|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$stringstring
$typeint

Returns

string|false
Quote a value using the native driverdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $pdo->quote("O'Reilly") // => "'O''Reilly'"
Calls 2
public static function getAvailableDrivers(): array<int, string>
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

array<int, string> Every driver name PDO itself was built with
List the available native driversdoctest
\ZtdQuery\Adapter\Pdo\ZtdPdo::getAvailableDrivers() === \PDO::getAvailableDrivers() // => true
Test cases 1
Calls 1
  • static-call PDO::getAvailableDrivers() line 425

Private surface 1§

Implementation details, listed for orientation only.

private ConnectionExecution $execution

Test cases 348§

Test cases that cover or call this symbol, from the coverage report and from the analyzed test sources.

Dedicated tests 26
Other tests reaching this symbol 322