Documentation · Chapter 07

Read and write
with PHP objects.

DbContext represents a work session with the database. DbSet represents all entities of one type.

We replace reading-list's temporary storage with SQLite without changing the application's purpose.

Create the context

src/Data/AppDbContext.php

phpaml — zsh
namespace App\Data;

use AML\Data\{DbContext, DbSet};
use App\Models\Book;

final class AppDbContext extends DbContext
{
    /** @return DbSet<Book> */
    public function books(): DbSet
    {
        return $this->set(Book::class);
    }
}

The four fundamental operations

phpaml — zsh
// Create
$book = new Book();
$book->title = 'The Pragmatic Programmer';
$book->author = 'Andrew Hunt & David Thomas';
$db->books()->add($book);

// Read
$books = $db->books()->orderBy('title')->all();
$book = $db->books()->find(1);

// Update
$book->title = 'New title';
$db->books()->update($book);

// Delete
$db->books()->remove($book);

Values are sent as PDO parameters; they are not concatenated into SQL. DbSet also limits query operators and validates column names from metadata.

Change tracking

phpaml — zsh
$book = $db->books()->find(1);
$book->title = 'Domain-Driven Design';

$count = $db->saveChanges(); // 1

An entity read by the context has a snapshot. saveChanges() compares the current object, detects its modification, and executes all writes in a transaction.

Filter and paginate

phpaml — zsh
$page = $db->books()
    ->where('author', 'LIKE', '%Martin%')
    ->orderBy('title', 'asc')
    ->paginate(page: 1, perPage: 20);

where(), orderBy(), and limit() return a new query object: the original query is unchanged. paginate() provides items, total, and page information.