kinetis / persistence
Request-scoped SQL transaction safety net, runtime-matched native DB drivers (mysqli async, ext-pgsql async, PDO), and the connection factory for Kinetis — MySQL and Postgres.
Requires
- php: ^8.4
- kinetis/framework: ^1.6
- revolt/event-loop: ^1.0
Requires (Dev)
- infection/infection: ^0.34.2
- nyholm/psr7: ^1.8
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.0
- vimeo/psalm: ^6.16
Suggests
- ext-mysqli: Needed by the native MySQL driver (Kinetis\Persistence\Driver\MysqliAsyncClient) — the default under FrankenPHP worker mode via DB_DRIVER=auto.
- ext-pdo_mysql: Needed by the PDO MySQL driver (Kinetis\Persistence\Driver\PdoMysqlClient) — the default under PHP-FPM via DB_DRIVER=auto.
- ext-pdo_pgsql: Needed by the PDO Postgres driver (Kinetis\Persistence\Driver\PdoPgsqlClient) — the default under PHP-FPM via DB_DRIVER=auto.
- ext-pgsql: Needed by the native Postgres driver (Kinetis\Persistence\Driver\PgsqlAsyncClient) — the default under FrankenPHP worker mode via DB_DRIVER=auto.
README
kinetis/persistence
Request-scoped SQL transaction safety net and connection factory for Kinetis
MySQL and Postgres via amphp/mysql/amphp/postgres, both sharing the
Amp\Sql\SqlLink/SqlTransaction abstraction — this package doesn't
need to know which one it's talking to.
use Kinetis\Persistence\SqlConnectionFactory; use Kinetis\Persistence\TransactionGuard; $db = SqlConnectionFactory::fromConfig($config); $guard->transaction($db, function ($tx) { $tx->execute('INSERT INTO orders (...) VALUES (...)'); });
SqlConnectionFactory::fromConfig() builds a runtime-matched driver
client from Kinetis\Config (the DB_* keys below, or their
DB_{NAME}_* named-connection equivalents), bound under
Contract\MysqlLink/Contract\PostgresLink automatically once
DB_CONNECTION is set — this package's bootstrap registers it before
the application's own bootstrap.php, which wins on the same binding.
TransactionGuard is the genuinely Kinetis-specific piece: request-scoped, autowired fresh
per RequestScope like any other unregistered class, tracking every
transaction it starts so a request that throws before committing or
rolling back doesn't leak an open transaction into whatever the pooled
connection is reused for next. Kinetis\Http\Kernel wires
rollbackDangling() into RequestScope::onDispose() automatically
whenever this package is installed — a genuine no-op for a request that
never opens one.
Optional: an application with no database at all can skip this package
entirely — Kinetis\Http\Kernel degrades gracefully (class_exists()
check, no dispose hook registered) when it isn't installed.
Provides
Installing this package is what opts it in — it registers the
following automatically, through the extra.kinetis declaration in its
composer.json (see
docs.kinetis.dev/cli.html):
- Service binding: with
DB_CONNECTIONset, the default connection is built and bound under its dialect contract (Kinetis\Persistence\Contract\MysqlLinkorContract\PostgresLink) before your ownbootstrap.phpruns — your registration wins on the same binding. Inert whenDB_CONNECTIONis unset.
Nothing else — no commands, routes, middleware, event listeners, or MCP tools.
Configuration
Read from the environment (or .env) via Kinetis\Config. Every key
is scoped.
| Key | Default | Purpose |
|---|---|---|
DB_CONNECTION |
(required) | mysql or pgsql. |
DB_HOST |
127.0.0.1 |
Server host. |
DB_PORT |
3306 / 5432 |
Per dialect. |
DB_NAME |
app |
Database name. |
DB_USER |
app |
User. |
DB_PASSWORD |
(required) | Password. |
DB_DRIVER |
auto |
auto (native under FrankenPHP worker mode, PDO otherwise), native, or pdo. |
DB_CHARSET |
utf8mb4 (MySQL) |
Connection charset. |
DB_COLLATION |
— | MySQL collation (SET NAMES ... COLLATE). |
DB_SSLMODE |
— | disable/require/verify-ca/verify-full on every driver; libpq additionally accepts allow/prefer. |
DB_SSL_CA |
— | CA bundle path for the verify modes. |
DB_CONNECT_TIMEOUT |
— | Seconds. |
DB_APP_NAME |
— | Postgres application_name. |
DB_COMPRESSION |
— | MySQL protocol compression. |
DB_MAX_CONNECTIONS |
8 |
Async drivers' pool width — per worker thread under FrankenPHP. |
DB_WARM_CONNECTIONS |
0 |
Connections opened at boot instead of first use — load-bearing for the mysqli driver under worker mode. |
DB_OPTIONS |
— | Legacy key=value string, translated where canonical equivalents exist. |
Scoped keys follow the named-connection convention — the connection
name inserts after the first segment: DB_HOST + reporting → DB_REPORTING_HOST.
Full reference across every package:
docs.kinetis.dev/config.html.
Installation
composer require kinetis/persistence
Requires PHP 8.4+ and kinetis/framework. Full documentation:
docs.kinetis.dev/persistence.html.
License
MIT — see LICENSE.