Skip to content

Getting Started

Muhammet Şafak edited this page May 24, 2026 · 1 revision

Getting Started

This page takes you end-to-end in about five minutes. Every snippet runs unchanged against SQLite in-memory — no server, no fixtures, no setup.

1. Open a connection

InitORM\DBAL\Connection\Connection is the single entry point. Its constructor accepts an associative credentials array that is merged on top of sensible defaults.

use InitORM\DBAL\Connection\Connection;

$db = new Connection([
    'driver'   => 'sqlite',
    'database' => ':memory:',
    'charset'  => '',
]);

Nothing has happened on the network yet. Connection is lazy — the PDO instance is created the first time you call getPDO(), query(), or any forwarded method.

2. Run a write

$db->getPDO()->exec(
    'CREATE TABLE users (
        id    INTEGER PRIMARY KEY,
        name  TEXT NOT NULL,
        email TEXT NOT NULL,
        active INTEGER NOT NULL DEFAULT 1
    )'
);

$db->query(
    'INSERT INTO users (name, email) VALUES (:name, :email)',
    ['name' => 'Alice', 'email' => 'alice@example.com']
);

$id = (int) $db->lastInsertId();   // PDO method, forwarded

Notes:

  • query() accepts named parameters as an associative array. The leading colon on each key is optional.
  • Values are bound with type-aware PDO constants. See Querying for the full mapping.
  • lastInsertId() is not defined on Connection — it lives on PDO and is forwarded via __call(). The same is true for beginTransaction(), commit(), rollBack(), quote(), and friends.

3. Run a read

$row = $db->query('SELECT id, name FROM users WHERE id = :id', ['id' => $id])
          ->asAssoc()
          ->row();

// ['id' => 1, 'name' => 'Alice']

Three things happen on the read:

  1. query() prepares the statement and binds :id with PARAM_INT.
  2. It returns a DataMapperInterface.
  3. asAssoc() sets the fetch mode (this is sticky); row() returns the next row, or null when there isn't one.

rows() returns every remaining row as an array (possibly empty):

$users = $db->query('SELECT id, name FROM users')->asAssoc()->rows();
// [['id' => 1, 'name' => 'Alice'], ...]

4. Hydrate into objects

final class User
{
    public int    $id    = 0;
    public string $name  = '';
    public string $email = '';
}

$users = $db->query('SELECT id, name, email FROM users')
            ->asClass(User::class)
            ->rows();

// $users is User[]

asObject() and asLazy() are also available — see DataMapper.

5. Wrap a unit of work in a transaction

$db->beginTransaction();
try {
    $db->query('INSERT INTO orders (user_id, total) VALUES (:u, :t)', ['u' => 1, 't' => 99]);
    $db->query('INSERT INTO order_items (order_id, sku) VALUES (:o, :s)',
        ['o' => $db->lastInsertId(), 's' => 'X-1']);
    $db->commit();
} catch (\Throwable $e) {
    if ($db->inTransaction()) {
        $db->rollBack();
    }
    throw $e;
}

There is no special transaction API — beginTransaction, inTransaction, commit, and rollBack are all forwarded to PDO. See Transactions for the gotchas around persistent connections.

6. See what ran

Switch on query logging when you need to inspect activity:

$db->setQueryLogs(true);

$db->query('SELECT 1');
$db->query('SELECT 2');

foreach ($db->getQueryLogs() as $entry) {
    echo $entry['query'], ' took ', $entry['timer'], "s\n";
}

The buffer lives in process memory. For production, prefer a real logger — see Logging.

Next steps

  • Connection — every credential, the lifecycle rules, and how clone() works.
  • Querying — bind types, prepare options, error handling.
  • DataMapper — fetch modes and result extraction.

Clone this wiki locally