Getting started
Four objects stand between you and a query. A ConnectionConfig describes a
connection, a Driver knows how to open it, a ConnectionManager hands out the
result by name, and a QueryGrammarResolver says which grammar compiles SQL for
which database.
Wire it up
use Dirthara\Database\Connection\ConnectionFactory;
use Dirthara\Database\Connection\ConnectionManager;
use Dirthara\Database\Connection\Driver\DriverName;
use Dirthara\Database\Connection\Driver\MySqlDriver;
use Dirthara\Database\Connection\Transaction\StandardTransactionGrammar;
use Dirthara\Database\Connection\ValueObjects\ConnectionConfig;
use Dirthara\Database\Connection\ValueObjects\SavepointPrefix;
use Dirthara\Database\Database;
use Dirthara\Database\Query\Grammar\MySqlQueryGrammar;
use Dirthara\Database\Query\Grammar\QueryGrammarResolver;
$grammar = new StandardTransactionGrammar(new SavepointPrefix());
$manager = new ConnectionManager(
new ConnectionFactory([new MySqlDriver($grammar)]),
[
new ConnectionConfig(
driver: DriverName::MySql,
name: 'primary',
host: 'mysql',
database: 'app',
username: 'app',
password: $password,
),
],
default: 'primary',
);
$database = new Database(
$manager,
new QueryGrammarResolver([DriverName::MySql->value => new MySqlQueryGrammar()]),
);
A driver is constructed with the transaction grammar
its database understands. MySQL, PostgreSQL, and SQLite take
StandardTransactionGrammar; SQL Server takes SqlServerTransactionGrammar.
Nothing has connected yet. Building the Database, the manager, or the resolver
never opens a socket; PDO is constructed on the first query.
Build a query
$rows = $database->table('users')
->select('id', 'name')
->where('role', '=', 'admin')
->orderBy('name')
->get();
$database->table('users')->insert(['name' => 'Ada', 'role' => 'admin']);
The builder compiles for whichever database the connection speaks. See Building queries for every clause.
Or write the SQL yourself
$rows = $database->execute('SELECT id, name FROM users WHERE role = ?', ['admin'])->all();
$database->execute('INSERT INTO users (name, role) VALUES (?, ?)', ['Ada', 'admin']);
$id = $database->connection()->lastInsertId();
execute() always returns a Result, for writes as well
as reads. For a write, affectedRows() is the interesting part.
Wrap it in a transaction
$database->transaction(function (ConnectedDatabase $db): void {
$db->table('accounts')->insert(['name' => 'Ada']);
$db->execute('UPDATE totals SET accounts = accounts + 1');
});
The callback receives a ConnectedDatabase
bound to the connection the transaction is running on, so the builder is
available inside it. The callback's return value is passed through. It commits
when the callback returns and rolls back when it throws, rethrowing the original
exception. Nested calls use savepoints.
A minimal SQLite setup
SQLite needs no host or credentials, which makes it the shortest way to try the package out — and the way its own test suite runs.
use Dirthara\Database\Connection\Driver\SQLiteDriver;
use Dirthara\Database\Query\Grammar\SQLiteQueryGrammar;
$database = new Database(
new ConnectionManager(
new ConnectionFactory([new SQLiteDriver($grammar)]),
[new ConnectionConfig(driver: DriverName::SQLite, database: ':memory:')],
),
new QueryGrammarResolver([DriverName::SQLite->value => new SQLiteQueryGrammar()]),
);
$database->execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
The config leaves name at its default of default, which is also the
manager's default connection name, so connection() resolves it without
arguments.
Next
- Database — named connections and how to scope work to one.
- Building queries — the builder's clauses.
- Expressions — when a string is quoted and when it is raw SQL.
- Connection configuration — every option and what it means.
- Executing queries — parameter binding rules.
- Error handling — which exception comes from where.