blueprintau / radiant
A database and ORM package for BlueprintAU — a fail-fast, explicit query builder, SQL connection layer, and attribute-driven ORM.
Requires
- php: ^8.4
- ext-pdo: *
- blueprintau/collections: ^1.0
- nesbot/carbon: ^3.13
Requires (Dev)
- nikic/php-parser: ^5.6
- phpstan/phpstan: ^2.2.16
- phpunit/phpunit: ^13.2
Suggests
- ext-pdo_mysql: Required to connect to MySQL databases.
- ext-pdo_pgsql: Required to connect to PostgreSQL databases.
- ext-pdo_sqlite: Required to connect to SQLite databases.
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-09 18:35:12 UTC
README
A database + ORM package for the BlueprintAU ecosystem — a fail-fast, explicit query builder, SQL connection layer, and attribute-driven ORM. Radiant is the database layer split out of the Lucent restructure.
Documentation
| Guide | Contents |
|---|---|
| Database layer | Connections, drivers, query builder, writes, transactions, streaming |
| The ORM | Models, #[Column], constraints, soft deletes, multi-table inheritance |
| Relations | HasOne/HasMany/BelongsTo, polymorphic (morphTo/MorphOne/MorphMany — allowlist-typed), many-to-many (BelongsToMany/MorphToMany), typed cache-aware reads, eager loading, through relations |
| Schema & sync | Blueprints, the differ, plan → show → apply, cross-process locking |
| CSV backend | The portable non-SQL connection and its limits |
| Safety | Injection-proofing, log-safe failures, fail-fast guarantees |
Installation
composer require blueprintau/radiant
Quick start
use BlueprintAU\Radiant\Database\DatabaseManager; $manager = new DatabaseManager([ 'mysql' => [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'port' => 3306, 'database' => 'app', 'username' => 'root', 'password' => '', ], ], default: 'mysql'); $db = $manager->connection(); $users = $db->table('users') ->where('active', '=', 1) ->orderBy('name') ->get(); // Collection<int, \stdClass>
Prefer a static facade over threading a DatabaseManager through your
code? Inject it once at bootstrap:
use BlueprintAU\Radiant\Database; Database::setManager($manager); // typically at application bootstrap $rows = Database::table('users')->where('active', '=', 1)->get();
ORM quick start
use BlueprintAU\Radiant\Model; use BlueprintAU\Radiant\Attributes\Column; use BlueprintAU\Radiant\Database\Schema\Enums\ColumnType; use Carbon\Carbon; class User extends Model { #[Column(type: ColumnType::BigInt, primaryKey: true, autoIncrement: true)] public int $id; #[Column(type: ColumnType::String, length: 255, unique: true)] public string $email; #[Column(type: ColumnType::DateTime, nullable: true)] public ?Carbon $emailVerifiedAt; } $user = User::find(1); $user->email = 'alicia@example.com'; $user->save();
Queries through the model return a Collection of hydrated model
instances (a blueprintau/collections subclass with model helpers like
find()).
Dependencies
blueprintau/collections— the one dependency that appears in Radiant's public API signatures: queries returnCollectioninstances.nesbot/carbon— first-class datetime support. Datetime columns holdCarboninstances on the model.
Everything else is PHP built-ins. No logging, no container, no cache.
Radiant reports via fail-fast exceptions (QueryException,
ConnectionException, UnsupportedFeatureException); the host framework
decides what to log. Wiring is explicit — no service locator, no DI lookup.
A failed query throws QueryException whose getMessage() is log-safe
by contract: it carries no SQL text and no bound values, so hosts can
log it unfiltered without leaking request-derived PII or credentials.
See Safety.
Philosophy
- Fail-fast exceptions. No silent fallbacks, no transparent caching that returns stale data. Radiant reports via exceptions; the host framework decides what to log.
- Explicit wiring. No container, no service locator, no static
registry.
DatabaseManagertakes the config array and default name in its constructor. - Portable core, gated extras. The generic
Connectioninterface runs a structured query against any backend (SQL, CSV, …). The ORM's core CRUD (find,all,where,save,delete— soft deletes included) works on anyConnection; SQL-only extras (joins, transactions, raw SQL, schema) throwUnsupportedFeatureExceptionon a non-SQL backend — never silently ignored. - Type-driven casting. Each column casts between the typed property value and a bindable value, driven by the PHP property type. The field is always set to the type the user expects.
Requirements
PHP 8.4 or newer.
Testing
composer install composer test # PHPUnit composer analyse # PHPStan (level 8) composer security:audit # dependency security advisories
composer.lock is committed, so CI checks dependencies against the
security advisories database over a reviewed, reproducible set; consumers
resolve their own versions as usual for a library.
CI runs the test suite across PHP 8.4 / 8.5 (lowest and highest dependencies) on every push and pull request, with MySQL and Postgres service containers for the integration suite. Releases are cut from the Release workflow (Actions → Release), which takes a version tag, verifies it does not already exist, runs the full test suite, then creates the tag and GitHub Release.
License
MIT — see LICENSE