alex-kassel / laravel-domain-core
High-cohesion Laravel platform foundation unifying Domain Context Registration, Dynamic Multi-Database Migrations, Context-Aware Eloquent Models, Standardized CLI Execution, Overlap Lock Management, Diagnostic Events, and Child Domain Package Scaffolding.
Package info
github.com/alex-kassel/laravel-domain-core
pkg:composer/alex-kassel/laravel-domain-core
Requires
- php: ^8.2
- illuminate/cache: ^11.0 || ^12.0 || ^13.0
- illuminate/console: ^11.0 || ^12.0 || ^13.0
- illuminate/contracts: ^11.0 || ^12.0 || ^13.0
- illuminate/database: ^11.0 || ^12.0 || ^13.0
- illuminate/events: ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^11.0 || ^12.0 || ^13.0
Requires (Dev)
- orchestra/testbench: ^9.0 || ^10.0
- phpunit/phpunit: ^10.5 || ^11.0
README
Polyglot domain storage contexts, dynamic multi-database provisioning, and ambient execution scoping
Installation • Storage Contexts • Ambient Scopes • Commands • Release Gate • Changelog
Laravel Domain Core is a high-cohesion platform foundation for modular Laravel applications. It unifies Polyglot Domain & Storage Context Registration, Dynamic Multi-Database & S3/Filesystem/Redis Provisioning, Context-Aware Base Eloquent Models, Standardized Operator CLI Execution, and Distributed Lock Management.
It introduces a clean architectural separation between Logical Business Contexts (StorageContext) and Physical Storage Mediums (StorageInterface):
Domain Profile (e.g., 'automotive-leasing')
└── StorageContext[] (e.g., 'primary', 'raw-html', 'transient-cache')
├── DatabaseStorage (connection: 'sqlite_leasing_primary', prefix: 'leasing_primary_', migrations: [...])
├── FileStorage (disk: 's3', basePath: 'leasing/raw-html/')
└── RedisStorage (connection: 'default', keyPrefix: 'leasing:cache:')
Key Features
- Polyglot Persistence Support: Register and manage relational databases (MySQL, PostgreSQL, SQLite), object storage/filesystems (Local, S3, MinIO), and in-memory caches (Redis) under a unified domain model.
- First-Class IDE Autocomplete & Type Safety: Strongly-typed Enum
StorageDriverType, dedicated named constructors (StorageContext::database(),::filesystem(),::redis()), and downcasting helpers ($context->asDatabase(),$context->asFilesystem()). - Context-Aware Eloquent Models & Hijacking Protection: Automatically route database connections and table prefixes at runtime; statically bound models cannot be hijacked by outer ambient scopes.
- Isolated Multi-Context Migrations: Filter database-backed contexts automatically and safely drop only domain-prefixed tables on shared connections via
domain:migrate --fresh. - Standardized Operator CLI DX & Distributed Locks: Uniform Artisan command flags (
--all,--domains,--context,--force,--dry-run,--lock-ttl) with robust lock management and POSIX signal handling (SIGTERM,SIGINT). - Actionable Diagnostics: Structured
[PROBLEM],[CAUSE], and[RESOLUTION]exceptions paired with diagnostic events (StorageConnectionMissing,CommandExecutionFailed,LockAcquisitionFailed). - Domain Package Scaffolding: CLI generator (
domain:make-domain) for standardized domain package skeletons.
Requirements
- PHP: 8.2+ (tested on 8.2, 8.3, 8.4, 8.5)
- Laravel Framework: 11.x | 12.x | 13.x
Installation
Install the package via Composer:
composer require alex-kassel/laravel-domain-core
The Service Provider AlexKassel\DomainCore\Providers\DomainCoreServiceProvider is automatically registered via Laravel Package Discovery.
Usage
1. Registering Domain Storage Contexts
Use dedicated named constructors for full IDE autocomplete:
use AlexKassel\DomainCore\Contracts\DomainRegistryInterface; use AlexKassel\DomainCore\DTOs\StorageContext; $registry = app(DomainRegistryInterface::class); // Register domain profile $registry->registerDomain( slug: 'automotive-leasing', name: 'Automotive Leasing', metadata: ['category' => 'vehicles'] ); // Register Relational Database Storage Context $registry->registerStorageContext(StorageContext::database( domainSlug: 'automotive-leasing', contextSlug: 'primary', connectionName: 'sqlite_leasing_primary', tablePrefix: 'leasing_primary_', migrationPaths: [__DIR__ . '/../database/migrations'], autoCreateSqliteDatabase: true )); // Register S3 / Filesystem Storage Context $registry->registerStorageContext(StorageContext::filesystem( domainSlug: 'automotive-leasing', contextSlug: 'raw-html', disk: 's3', basePath: 'leasing/raw-html/' )); // Register Redis Storage Context $registry->registerStorageContext(StorageContext::redis( domainSlug: 'automotive-leasing', contextSlug: 'transient-cache', connection: 'default', keyPrefix: 'leasing:cache:' ));
2. Ambient Execution Scopes
Execute business logic within an isolated domain and storage context:
use AlexKassel\DomainCore\Facades\DomainContext; use AlexKassel\DomainCore\DTOs\StorageContext; // Database Scope: DomainContext::using('automotive-leasing', 'primary', function (StorageContext $context) { // Eloquent models automatically resolve connection and prefix $item = new App\Models\LeasingOffer(); $item->title = 'Audi A4 Lease'; $item->save(); }); // Filesystem Scope: DomainContext::using('automotive-leasing', 'raw-html', function (StorageContext $context) { $disk = DomainContext::disk(); // Returns Laravel Filesystem disk ('s3') $disk->put('payload_123.html', $htmlContent); });
3. Context-Aware Base Eloquent Models
Extend ContextAwareModel or use HasDomainContextTrait:
use AlexKassel\DomainCore\Database\Models\ContextAwareModel; class LeasingOffer extends ContextAwareModel { protected $table = 'offers'; protected $fillable = ['title', 'price', 'vin']; }
Static Domain Binding & Hijacking Protection
For models permanently bound to a specific domain that must ignore outer ambient scopes:
class ArchiveOffer extends ContextAwareModel { protected ?string $explicitDomain = 'automotive-leasing'; protected ?string $explicitContext = 'archive'; protected $table = 'archives'; }
4. Running Multi-Database Migrations
MigrationManager automatically filters relational database contexts and skips non-relational storage:
use AlexKassel\DomainCore\Contracts\MigrationManagerInterface; $migrationManager = app(MigrationManagerInterface::class); $reports = $migrationManager->migrate( domainSlug: 'automotive-leasing', contextSlug: 'primary', force: true );
5. CLI Execution & Distributed Lock Management
Execute batch jobs across domains safely with distributed locking and signal traps:
use AlexKassel\DomainCore\Contracts\CommandRunnerInterface; use AlexKassel\DomainCore\DTOs\DomainProfile; $runner = app(CommandRunnerInterface::class); $options = $runner->parseCliOptions([ 'all' => true, 'domains' => 'domain-one,domain-two', 'context' => 'primary', 'lock-ttl' => 300, ]); $targetDomains = $runner->resolveTargetDomains($options); foreach ($targetDomains as $domain) { $report = $runner->executeDomain( domain: $domain, componentKey: 'scraper-job', callback: function (DomainProfile $profile) { // Execution protected by distributed lock return 42; // Items processed count }, options: $options ); }
Commands
All package commands are grouped under the domain: namespace:
| Command | Description |
|---|---|
domain:status |
Display registration, connection, driver, and prefix/path across domains |
domain:migrate |
Execute database migrations across registered domain storage contexts |
domain:cache |
Compile and atomically cache registered domain contexts for production |
domain:clear |
Clear compiled domain context cache |
domain:make-domain |
Scaffold a new domain package skeleton |
Testing
From the monorepo root, run the complete package verification pipeline:
composer pkg:check alex-kassel/laravel-domain-core --json
Changelog
Please see CHANGELOG.md for more information on what has changed recently.
Security Vulnerabilities
Please review the security policy to report vulnerabilities.
License
The MIT License (MIT). Please see License File for more information.