danielmewes/php-rql
php-rql is a PHP client driver for RethinkDB. It lets PHP applications connect to a RethinkDB server, build ReQL queries with a fluent API, execute them synchronously or asynchronously, and process results, making it easy to integrate RethinkDB’s realtime NoSQL database into PHP projects.
composer require danielmewes/php-rql. Autoload is the r\ namespace — there is no PSR-4 base class to learn; you interact with global r\ functions (r\connect, r\table, r\db, r\row, r\now, …) and r\Connection / r\Query / r\Cursor objects.localhost:28015) and a database, usually created ad hoc: r\dbCreate('app')->run($conn).require 'vendor/autoload.php';
$conn = r\connect('localhost', 28015, 'app'); // host, port, db
// or: r\connect(['host' => '...', 'port' => 28015, 'db' => 'app', 'timeout' => 5])
r\table('users')->insert(['name' => 'Ada', 'age' => 36])->run($conn);
$adults = r\table('users')->filter(r\row('age')->ge(18))->run($conn);
foreach ($adults as $user) { /* $user is a PHP array */ }
filter, getAll, group, changes) — php-rql mirrors the JS driver almost 1:1 with \ for . and r\row('x') instead of r.row('x'). Then scan r\Connection and r\Datum in the source for options (timeout, ssl, apiKey).r\Query. You can compose, store, and pass queries around — nothing hits the server until ->run($conn). This makes it natural to inject a query builder into a service.r\row: r\table('users')->filter(r\row('tags')->contains('admin')). r\row is only valid inside a filter/map context.$cursor = r\table('events')->run($conn);
foreach ($cursor as $doc) { ... } // streaming
// or ->toArray($conn) for small sets
Prefer foreach for anything unbounded; toArray() materializes everything in memory.getAll: r\table('users')->getAll('[email protected]', ['index' => 'email'])->run($conn). Always pass ['index' => ...] after creating it: r\table('users')->indexCreate('email')->run($conn).r\table('orders')->group('status')->count()->run($conn) — but call ->ungroup() if you want a plain PHP array rather than a grouped stream.r\now(), r\epochTime($ts), r\ISO8601($str). Stored values come back as r\Datum; call ->toNative() on a datetime datum to get a \DateTime.$feed = r\table('orders')->changes(['include_initial' => true])->run($conn);
foreach ($feed as $change) { ... } // blocks until next change
r\dbCreate, r\tableCreate, r\indexCreate, r\table('x')->wait() — run these idempotently (catch RqlServerError for "already exists").r\Connection per process (singleton / DI container binding). Reuse it across requests in Octane/Swoole or queue workers; don't r\connect() per query.r\table('x')->delete()->run($conn) between tests, or use a per-run DB name and r\dbDrop in teardown.[] is ambiguous. r\expr([]) is treated as an array. Force an empty object with r\object() (or (object) []) when the server schema expects one. Same issue for associative arrays with numeric-string keys — PHP collapses them, so key order/type can surprise you.foreach early, the cursor isn't fully drained. Close the connection or let the cursor finish when possible; abandoned cursors can stall a connection pool.r\RqlDriverError (transport/protocol issues — reconnect) vs. r\RqlServerError (query invalid, table missing, etc. — fix the query). Catch both at boundary layers; don't swallow server errors.group() needs ungroup() to be usable in normal PHP code — otherwise you get an opaque grouped stream.r\row name collision: if a document actually has a field named row, r\row('row') still works, but be careful when building dynamic field names — prefer explicit strings.ArrayAccess/Countable on r\Datum. Run a small smoke test before upgrading PHP.timeout closes the connection after idle time. For long-lived workers, either set it high or catch driver errors and reconnect — do not silently reuse a dead r\Connection.$query->toString() (or cast) prints the ReQL the driver will send — invaluable when a query "should work" but errors. Server profiles via ->run($conn, ['profile' => true]) help when latency is the mystery.->squelch() on the cursor (or suppress the "unchanged" warnings) or you'll log spurious notices; also always guard the loop with a shutdown/stop signal — otherwise the worker never exits.['ssl' => true, 'ca' => '/path/ca.pem'] and check the server cert's hostname; misconfigured CA paths manifest as opaque RqlDriverErrors, not helpful TLS messages.r\Connection is possible for connection factories/observers, but most teams just wrap it in a thin service class that owns reconnect logic and exposes typed helpers per collection.How can I help you explore Laravel packages today?