A PDO-compatible wrapper for the Sqlx PHP extension, designed to ease migration of existing PDO-based code.
<?php
require_once 'pdo.php';
// Create connection
$pdo = new PdoEmulator\PDO('pgsql:host=localhost;dbname=mydb', 'username', 'password');
// Set attributes
$pdo->setAttribute(PDO::ATTR_ERRMODE, PdoEmulator\PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PdoEmulator\PDO::FETCH_ASSOC);
// Simple query
$stmt = $pdo->query("SELECT * FROM users WHERE active = true");
foreach ($stmt as $row) {
echo $row['name'] . "\n";
}
// Prepared statement with positional parameters
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([123]);
$user = $stmt->fetch();
// Prepared statement with named parameters
$stmt = $pdo->prepare("SELECT * FROM posts WHERE author_id = :author_id AND status = :status");
$stmt->execute(['author_id' => 456, 'status' => 'published']);
$posts = $stmt->fetchAll();
// Insert and get last ID
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->execute(['John Doe', 'john@example.com']);
$lastId = $pdo->lastInsertId();PDO-style transactions (beginTransaction(), commit(), rollBack()) have limited functionality due to architectural differences between PDO and Sqlx:
- PDO uses explicit begin/commit/rollback calls
- Sqlx uses a callback-based transaction API
The current implementation only tracks transaction state internally but does not create real database transactions.
For real transaction support, use the native Sqlx API:
<?php
$driver = \Sqlx\DriverFactory::make('postgres://user:pass@localhost/db');
$driver->begin(function($driver) {
// All queries here run in a transaction
$driver->execute('INSERT INTO users (name) VALUES (?)', ['John']);
$driver->execute('UPDATE accounts SET balance = balance - 100 WHERE user_id = ?)', [1]);
// Return true to commit, false to rollback
return true;
});If an exception is thrown inside the callback, the transaction is automatically rolled back.
For nested transaction-like behavior, use savepoints:
<?php
$driver->begin(function($driver) {
$driver->execute('INSERT INTO users (name) VALUES (?)', ['John']);
// Create savepoint
$driver->savepoint('sp1');
try {
$driver->execute('INSERT INTO logs (message) VALUES (?)', ['Action logged']);
} catch (\Exception $e) {
// Rollback to savepoint
$driver->rollbackToSavepoint('sp1');
}
// Release savepoint if no longer needed
$driver->releaseSavepoint('sp1');
return true;
});FETCH_ASSOC- Associative arrayFETCH_OBJ- Object (stdClass)FETCH_BOTH- Converted to FETCH_ASSOC (not true both)FETCH_NUM- Numeric array (via array_values)
ERRMODE_SILENT- No errors reportedERRMODE_WARNING- PHP warningsERRMODE_EXCEPTION- Throws PDOException
ATTR_ERRMODE- Error reporting modeATTR_DEFAULT_FETCH_MODE- Default fetch mode for statementsATTR_DRIVER_NAME- Database driver name (mysql, pgsql, sqlsrv)
__construct($dsn, $username, $password, $options)- Create connectionprepare($statement)- Prepare a statementquery($statement, $mode)- Execute query and return result setexec($statement)- Execute statement and return affected rowslastInsertId($name)- Get last inserted IDbeginTransaction()- Begin transaction (⚠️ limited)commit()- Commit transaction (⚠️ limited)rollBack()- Rollback transaction (⚠️ limited)inTransaction()- Check if in transactionsetAttribute($attribute, $value)- Set attributegetAttribute($attribute)- Get attributeerrorInfo()- Get error information
bindParam($param, &$var, $type)- Bind parameter by referencebindValue($param, $value, $type)- Bind parameter by valueexecute($params)- Execute prepared statementfetch($fetch_style)- Fetch next rowfetchAll($fetch_style)- Fetch all rowsrowCount()- Get row countcolumnCount()- Get column countcloseCursor()- Close cursorerrorInfo()- Get error information- Iterator methods:
current(),key(),next(),rewind(),valid()
- Transactions - PDO-style transaction methods do not create real database transactions
- FETCH_BOTH - Not truly "both", converts to FETCH_ASSOC
- FETCH_NUM - Implemented via array_values() on FETCH_ASSOC
- Parameter Types - Type hints in
bindParam()are ignored - Column Metadata -
getColumnMeta()not implemented (returns false) - Some PDO Attributes - Not all PDO attributes are supported
- Statement Options -
prepare()driver options are ignored
The emulator converts PDO DSN format to Sqlx URL format:
// MySQL
'mysql:host=localhost;port=3306;dbname=mydb'
→ 'mysql://user:pass@localhost:3306/mydb'
// PostgreSQL
'pgsql:host=localhost;port=5432;dbname=mydb'
→ 'postgres://user:pass@localhost:5432/mydb'
// SQL Server
'sqlsrv:host=localhost;port=1433;dbname=mydb'
→ 'mssql://user:pass@localhost:1433/mydb'Run the comprehensive test suite:
php pdo-test.phpOr use the simple example:
php pdo.example.phpIf you want full Sqlx features, consider migrating:
// PDO style
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([123]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// Sqlx native style
$driver = \Sqlx\DriverFactory::make('postgres://...');
$user = $driver->queryRowAssoc("SELECT * FROM users WHERE id = ?", [123]);- True transaction support with callbacks
- Better performance (no emulation overhead)
- Advanced features like query builders
- Conditional SQL blocks
{{ AND field = :param }} - Safe
IN (?)clause expansion - Native JSON support
- Connection pooling
See the main README.md for full Sqlx documentation.
When improving this emulator:
- Maintain backward compatibility where possible
- Document any limitations clearly
- Add tests for new features
- Update this README with changes
MIT - Same as the main php-sqlx project