pdo-cfd1
pdo-cfd1 connects PHP’s PDO interface to actual
Cloudflare D1 bindings. The dedicated
php-cloud-wasm profile statically
includes the driver for PHP 8.0–8.5, including the upstream PHP
8.0 PDO callback adapters. It does not require a browser/Node
extension loader.
Start with PHP in
Cloudflare for the complete build, raw Wasm module upload,
Pages configuration and deployment guide. An ordinary
PhpWorker build is not interchangeable with this
Cloudflare profile.
Runtime setup
Import a version-bound entry from the complete package and create the PHP instance inside each Worker request:
import { PhpCloudflare } from './php-cloud-wasm/php8.5-cloudflare.mjs';
const php = new PhpCloudflare({
cfd1: { mainDb: env.DB },
});The example assumes a copied package beside your Worker
entry. env.DB is the Worker’s configured D1
binding; mainDb is the PHP-facing name. The
generated entry supplies the matching precompiled Wasm module
and runtime factory.
Query D1 through PDO
Use cfd1:<mapKey> and prepared-statement
parameters:
await php.run(`<?php
$pdo = new PDO('cfd1:mainDb', null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$query = $pdo->prepare('SELECT ? AS answer');
$query->execute([42]);
echo json_encode($query->fetch(PDO::FETCH_ASSOC));
`);This query needs no schema. Capture the runtime’s
output event to form the HTTP response, as shown in
the setup guide. Ordinary execute([...]) does not
require explicit binding and uses PDO’s default
PDO::PARAM_STR convention. Use typed
bindValue or bindParam when integer,
boolean, NULL, or BLOB types matter. Numeric binding positions
start at 1; numeric execute-array keys start at 0. Named
parameters accept names with or without the leading colon.
Supported scope and errors
- Bare
?, numbered?NNN, and PDO-style:nameparameters. Repeated names reuse one value; do not mix named and positional parameters in a statement. query(),exec(), repeatedexecute(), normal PDO fetch modes, and cursor reuse. WriterowCount()uses D1’s changes count, not the SELECT result size.quote()for text and BLOB literals, and per-connectionlastInsertId(). Insert IDs outside JavaScript’s safe integer range cannot be reported exactly; use an explicit text-valuedRETURNINGquery when needed.- Binary strings and readable streams through
PDO::PARAM_LOB, with binary strings returned for BLOB results. Empty BLOBs remain distinct from NULL. - Buffered scroll cursors selected with
PDO::CURSOR_SCROLL, andgetColumnMeta()based on observed result values. D1 does not supply table origins or declared schema metadata through this result interface. - Missing bindings and failed queries report PDO errors.
Exception mode raises
PDOException; warning and silent modes returnfalsewith error details.
Atomic batches
cfd1Batch() submits distinct prepared statements
from the same PDO connection as one atomic D1 batch. Bind
parameters before submitting them:
$insert = $pdo->prepare('INSERT INTO users (name) VALUES (:name)');
$insert->bindValue('name', 'Alice');
$select = $pdo->prepare('SELECT name FROM users ORDER BY name');
$pdo->cfd1Batch([$insert, $select]);
$users = $select->fetchAll(PDO::FETCH_ASSOC);The example assumes a users table with a
name column. Each statement receives its own
results and affected-row count. Validation occurs before
submission; database statement failures roll back the batch.
Transport failures are not retried automatically because the
commit outcome may be unknown. Do not call
execute() just to populate batch bindings: it
executes that statement immediately.
Open PDO transactions, persistent connections, output
parameters, streaming cursors, multiple result sets, and
@name / $name placeholders remain
unsupported. A batch is a predetermined group; PHP cannot read
intermediate results and choose additional statements inside it.
See the integration guide below for parameter limits, cursor
behavior, metadata and error details.
The Cloudflare build imports the pinned upstream driver
directly, without an ad-hoc compatibility patch. Custom builds
can select PDO_CFD1_REF or a local
PDO_CFD1_DEV_PATH. The legacy
php-static PDO example uses a vrzno: DSN, which
must be migrated to the binding map and cfd1: API
above.
See the PDO-CFD1 integration guide, upstream driver, and Cloudflare D1 bindings.