SQLCraft is a framework-independent PHP 8.4+ SDK for database administration. It provides typed connection, metadata, DDL, query, import, export, capability, and event primitives while keeping PDO, HTTP, UI, and application state out of consumer code.
SQLCraft is in the v1.0 release-candidate phase. The supported platforms are SQLite, MySQL, MariaDB-compatible MySQL deployments, PostgreSQL, and Microsoft SQL Server. Oracle support is intentionally deferred to a future milestone and is not part of this release.
composer require vendor/sqlcraftSQLCraft requires ext-pdo. Install the PDO extension for each engine you plan
to use:
ext-pdo_sqlitefor SQLiteext-pdo_mysqlfor MySQL and MariaDBext-pdo_pgsqlfor PostgreSQLext-pdo_sqlsrvorext-pdo_dblibfor Microsoft SQL Server
The package does not require a framework or PSR implementation at runtime. Optional PSR event, logging, and cache integrations are suggested dependencies.
The following complete script creates an in-memory database, inserts a row, and streams the result through SQLCraft's connection boundary:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use SQLCraft\Connection\PdoConnectionFactory;
use SQLCraft\Connection\PdoExceptionTranslator;
use SQLCraft\Driver\SqliteDriver;
use SQLCraft\Platform\SqlitePlatform;
use SQLCraft\ValueObjects\ConnectionParameters;
$connectionFactory = new PdoConnectionFactory(new PdoExceptionTranslator());
$driver = new SqliteDriver($connectionFactory, new SqlitePlatform());
$database = $driver->connect(new ConnectionParameters(database: ':memory:'));
$database->execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
$database->execute('INSERT INTO users (name) VALUES (?)', ['Ada']);
foreach ($database->query('SELECT id, name FROM users', streaming: true) as $row) {
printf("%d: %s\n", $row['id'], $row['name']);
}Run the same script from the repository with:
php examples/01-basic-connection.phpEvery numbered example is runnable after composer install and uses SQLite by
default, so no engine container or external service is required:
examples/01-basic-connection.php— connect, write, and stream rowsexamples/02-schema-introspection.php— inspect tables and columnsexamples/03-ddl-create-table.php— render and execute a DDL builderexamples/04-query-and-paginate.php— allowlisted filtering and paginationexamples/05-import-export.php— streaming row export and importexamples/06-laravel-integration.php— thin service-provider binding shapeexamples/07-symfony-integration.php— thin service-definition shapeexamples/08-multi-engine-comparison.php— engine-independent operation shapeexamples/09-transactions.php— commit and rollback on a balance transferexamples/10-alter-table.php— render alter-table DDLexamples/11-create-index.php— render create/drop index DDLexamples/12-structured-export.php— SQL export via Exporter + SqlFormatWriterexamples/13-csv-import.php— CSV import into a tableexamples/14-event-hooks.php— PSR-14 query listenersexamples/15-credential-providers.php— array and env credential providersexamples/16-connection-manager.php— named multi-connection registryexamples/17-capability-detection.php— platform capability checksexamples/18-export-formats.php— JSON/XML/XLSX/HTML export (writesexamples/out/)
SQLCraft follows a small hexagonal boundary:
DriverInterfaceowns engine-specific DSN construction and platform choice.ConnectionInterfaceowns database I/O; PDO types never leaveSQLCraft\\Connection.PlatformInterfaceowns quoting, capability checks, SQL rendering, and engine dialect.SchemaManager, DDL builders,QueryExecutor, and import/export services use typed contracts above the connection layer.- PSR-14 events, when supplied, observe and intercept operations without adding a framework dependency.
For applications that need a container, register the driver registry and typed connection factory in the container. Laravel and Symfony should bind SQLCraft alongside their native database services, not replace them. The integration shapes are shown in the two framework examples.
Query execution is streaming by default in QueryExecutor::query(), limiting
memory use for large result sets. Use the explicit buffered: true escape hatch
when random access, count(), or a fully materialized result is required.
Import and export services process data in chunks and expose progress events.
SQLCraft separates values from SQL parameters and validates identifiers, operators, aggregate functions, data types, pagination limits, statement counts, and import sizes at their boundaries. User-controlled values are never interpolated into rendered query SQL. Credentials are marked sensitive and redacted from DSNs, logs, and exception text.
Capability checks are explicit:
if (!$database->getPlatform()->has(\SQLCraft\Capabilities\Capability::Trigger)) {
// Select a documented fallback instead of issuing unsupported DDL.
}Use require() when an operation cannot continue without a capability; it
throws SQLCraft\\Capabilities\\CapabilityNotSupportedException with typed
capability, platform, and version context.
cp .env.example .env
docker compose build php
docker compose run --rm php composer install
docker compose run --rm php composer run ciThe php service is deliberately independent of engine services. M0–M1 checks
run with only the PHP container. Start database services separately for
integration tests from M2 onward:
docker compose up -d
docker compose run --rm php composer run test:integrationOracle is deferred; no Oracle service is required for the default development or CI workflow.
The complete implementation design lives in docs/plans/:
23-roadmap.md— milestone goals and acceptance gates18-public-api.md— consumer workflows and API policy19-package-structure.md— package layout and tooling20-testing.md— unit, integration, contract, and golden tests21-performance.md— streaming and query-count guarantees25-final-review.md— resolved design decisions and hard edges
SQLCraft is released under the MIT License.