1tomany/rich-bundle
Symfony bundle implementing the RICH (Request, Input, Command, Handler) architecture. Encourages single-responsibility actions with explicit Input/Command/Handler classes for clear, safe, and futureproof backend development without heavy DDD/CQRS overhead.
Input/Command/Handler flow.Contract layer mirrors Laravel’s interfaces/repositories pattern.Command/Handler design is compatible with Laravel’s Queues (e.g., dispatch()) or Laravel Horizon, enabling future async scaling without refactoring.Serializer, Validator, and HttpFoundation. Laravel alternatives:
Validator or FormRequest.Laravel\Serializable or spatie/array-to-object.Input classes to Laravel’s FormRequest or Illuminate\Http\Request.RepositoryInterface pattern can be replicated with Laravel’s Repository pattern (e.g., spatie/laravel-repository).#[SourceUser] or #[SourceIpAddress] are Symfony-specific. Mitigation: Create Laravel-specific attributes or middleware to map request data to Input objects.Container vs. Laravel’s Service Provider. Mitigation: Use Laravel’s bindings or tagging to register handlers as services.Source* attributes) may impact performance. Mitigation: Benchmark and optimize with Laravel’s macroable or custom trait-based mapping.CreateUserHandler in Laravel’s app/Commands directory).Input/Command flow to Laravel’s request lifecycle?
Input classes extend FormRequest or use middleware to populate DTOs?Handler classes directly (e.g., via middleware)?Illuminate\Validation\Validator) vs. Symfony’s Validator?
Handler classes with Laravel Queues? Will we use dispatch() or a custom command bus?Handler classes in isolation (e.g., mocking repositories) in Laravel’s testing framework?Input with Laravel’s FormRequest or custom DTOs (e.g., spatie/data-transfer-object).Validator or FormRequest rules instead of Symfony’s Assert constraints.Handler classes and RepositoryInterface implementations.Handler classes via middleware or controller adapters (e.g., HandleCreateAccount middleware).laravel-softwarearchitects/command-bus for async Handler execution.Events or Laravel Echo.Mockery or PestPHP to test Handler classes in isolation.User or Post) and refactor it using RICH principles in Laravel.UserController with:
CreateUserInput (extends FormRequest).CreateUserCommand (DTO).CreateUserHandler (service class).Serializer/Validator with Laravel equivalents.RichServiceProvider to bind Handler interfaces to implementations.Handler-based middleware.Handler execution.| Symfony Component | Laravel Equivalent |
|---|---|
HttpFoundation\Request |
Illuminate\Http\Request |
Validator |
Illuminate\Validation\Validator |
Serializer |
spatie/array-to-object |
EventDispatcher |
Illuminate\Events\Dispatcher |
Container |
Illuminate\Container |
Source* behavior.app/Modules/Account/Handlers, app/Modules/Account/Commands).app/
Modules/
Account/
Actions/
Commands/
CreateAccountCommand.php
Handlers/
CreateAccountHandler.php
Input/
CreateAccountRequest.php (extends FormRequest)
Contracts/
Repository/
AccountRepositoryInterface.php
Input classes to Laravel FormRequest or DTOs.// app/Modules/Account/Actions/Input/CreateAccountRequest.php
namespace App\Modules\Account\Actions\Input;
use Illuminate\Foundation\Http\FormRequest;
use App\Modules\Account\Actions\Commands\CreateAccountCommand;
class CreateAccountRequest extends FormRequest {
public function rules(): array {
return [
'name' => 'required|string|max:128',
'email' => 'required|email|max:128',
];
}
public function toCommand(): CreateAccountCommand {
return new CreateAccountCommand(
$this->user()->id,
$this->name,
$this->email,
);
}
}
Handler classes with Laravel’s ServiceProvider bindings.// app/Modules/Account/Actions/Handlers/CreateAccountHandler.php
namespace App\Modules\Account\Actions\Handlers;
use App\Modules\Account\Actions\Commands\CreateAccountCommand;
use App\Modules\Account\Contracts\Repository\AccountRepositoryInterface;
class CreateAccountHandler {
public function __construct(
private AccountRepositoryInterface $repository
) {}
public function handle(CreateAccountCommand $command) {
$this->repository->create($command);
}
}
// app/Http/Middleware/DispatchHandler.php
namespace App\Http\Middleware;
use Closure;
use App\Modules\Account\Actions\Handlers\CreateAccountHandler;
class DispatchHandler {
public function __invoke(CreateAccountHandler $handler, Closure $next) {
$handler->handle($this->request->toCommand());
return $next($request);
}
}
Route::post('/accounts', CreateAccountRequest::class)
->middleware(DispatchHandler::class);
Handler classes (mock repositories).Handler or Input class won’t ripple acrossHow can I help you explore Laravel packages today?