Skip to content

Eloquent and the query builder

atoms/database-illuminate boots illuminate/database against the SQLite database an Atom already owns, so an Atom can use the Laravel query builder and Eloquent models over its durable state.

The bridge runs inside the Atom, which means it belongs in atoms-composer.json alongside illuminate/database, not in your application’s composer.json:

{
"require": {
"atoms/database-illuminate": "^0.6",
"illuminate/database": "^12.0"
}
}

atoms build and atoms deploy include these packages with your Atom code. See atoms-composer.json for what the file accepts and how its lock file pins versions.

EloquentBridge::boot() takes the Atom’s database and returns a connection you can call query builder methods on. It also registers that connection as Eloquent’s default, so call it before touching a model.

namespace App\Atoms;
use Atoms\Atom;
use Atoms\DatabaseIlluminate\EloquentBridge;
use App\Atoms\GameRoom\Support\Score;
class GameRoom extends Atom
{
public function record(string $player, int $score): array
{
$db = EloquentBridge::boot($this->db());
$db->table('scores')->insert(['player' => $player, 'score' => $score]);
return Score::query()
->orderByDesc('score')
->limit(10)
->get()
->toArray();
}
}

Models are Atom-side classes: keep them in the Atom’s support/ directory, where they ship with the Atom and follow the same import rules as the Atom class itself.

Return array shapes from Atom methods. An Eloquent model carries a connection and behavior, so it is not a value that crosses the boundary — call ->toArray(), or map to a shared DTO, before returning.

The bridge runs against the Atom’s own database, inside the runtime, so a few behaviors differ from the connection you’d get in a Laravel app.

An inner transaction() joins the transaction already open, the same way $this->db()->transaction() does. To roll back, throw from inside the closure.

Don’t call rollBack() by hand inside a nested transaction(). It discards every write since the outermost transaction began, and the enclosing transaction() calls then fail because the transaction is already closed.

afterCommit() and afterRollBack() aren’t supported; calling them throws.

Schema changes go through Atoms migrations

Section titled “Schema changes go through Atoms migrations”

The bridge is for queries and models, and it refuses Laravel’s schema builder — Schema::create() and everything else that goes through getSchemaBuilder() throws. To change an Atom’s schema, add a migration file to the Atom’s migrations/ directory; the runtime applies it the next time the Atom wakes up. See lifecycle for how migrations run.

The bridge installs no event dispatcher, so creating, saved, and the other model events never fire, and observers never run. Timestamps, casts, and relationships work as usual.

getServerVersion() doesn’t reach the database

Section titled “getServerVersion() doesn’t reach the database”

The runtime can’t ask SQLite for its version, so the bridge reports a recent one by default. To report a specific version, pass ['server_version' => '...'] as the second argument to EloquentBridge::boot().

As with any read inside an Atom, integer values above 2^53-1 come back imprecise unless you read them as text. Read large integers as text covers the workaround.