leafs/db · framework agnostic
Db is a query builder that reads like English. MySQL, Postgres, SQLite and SQL Server through one tiny API; prepared statements everywhere, no ORM classes to configure, in any PHP app.
| id | name | role |
|---|
Toggle the chips — the query, the SQL and the results stay in sync. Values always travel as bindings.
Most database layers make you choose: raw PDO boilerplate, or an ORM with models, migrations, and a manual. Db is the third option — a fluent builder small enough to learn in minutes, safe enough to trust with user input, and honest enough to show you the SQL it runs.
Everything you need
Four databases, one API
MySQL, Postgres, SQLite and SQL Server. Same code, different dbtype.
Prepared, always
Every value you pass travels as a binding — never glued into the SQL string.
Multiple connections
Name your connections, switch per-query with use(). Reads, writes, analytics — sorted.
Zero ORM overhead
No models, no migrations, no annotations. One class, one require, done.
The builder
Say what you want, the way you'd say it out loud. Db turns it into parameterised SQL — in, not in and between included.
$admins = db() ->select('users') ->where('role', 'admin') ->orderBy('created_at', 'desc') ->limit(10) ->all(); // or reach for the helpers $user = db()->select('users')->find(1); $vips = db()->select('users') ->where('plan', 'in', ['pro', 'team'])->all();
$saved = db() ->insert('users') ->params([ 'name' => $name, 'email' => $email, ]) ->unique('email') ->execute(); if (!$saved) { // ['email' => 'email already exists'] return db()->errors(); }
Safe writes
Mark a field unique() and duplicates are rejected before they ever hit your table — with a readable error you can hand straight back to the user. The check runs as a prepared statement, so hostile input stays data.
Relations
with() pulls related rows along in both directions — a post's author, or an author's posts — keyed by convention, overridable when your schema disagrees.
// a post, with its author attached $post = db()->select('posts') ->where('id', 1) ->with('users', 'user_id') ->first(); $post['user']['name']; // 'Mika' // an author, with all their posts $author = db()->select('users') ->where('id', 1) ->with('posts') ->first();
Grown-up features
Multiple connections
db()->addConnections([ 'main' => [/* mysql */], 'analytics' => [/* postgres */], ], 'main'); // per-query switching db('analytics')->select('events')->all();
Transactions
$ok = db()->transaction(function ($db) { $db->insert('orders')->params($order)->execute(); $db->update('stock')->params(['qty' => $qty]) ->where('sku', $sku)->execute(); }); // false? everything rolled back. no partial orders.
Bring your stack
Db needs PHP and PDO — that's the whole list. Use the Leaf\Db class directly anywhere; the db() helper lights up inside Leaf.
Then connect and query — or read the full documentation.