lorisleiva/laravel-actions
Organize app logic into single-purpose “Action” classes that can run as controllers, jobs, listeners, commands, and more. Define a handle method for the core task, then add asController/asJob/etc wrappers to reuse the same logic across contexts.
PublishANewArticle). This aligns well with Domain-Driven Design (DDD) and Clean Architecture, where actions encapsulate workflows rather than HTTP/queue/event concerns.run()) and mockable, simplifying test suites. The make:action Artisan command even scaffolds test stubs.asController, asJob), reducing friction for developers.JobDecorator, ControllerDecorator) for tailored behavior, e.g., custom validation or middleware.run() method. The package mitigates this with backtrace frame limits and custom error handling (e.g., jobFailed(Throwable $e)).asX()) adds slight reflection costs. Benchmarks show negligible impact for typical use cases.jobFailed) be monitored/logged?asController).asJob).asListener).asCommand).HttpFoundation for request handling).asController.| Phase | Approach | Tools/Examples |
|---|---|---|
| Assessment | Audit existing controllers/jobs for reusable logic. | Use php artisan make:action to scaffold candidates. |
| Pilot | Replace 1–2 controllers with actions, keeping routes/jobs unchanged. | Example: Convert ArticleController@store → PublishArticle action. |
| Incremental | Refactor one concern per action (e.g., asJob, asListener). |
Use asController for HTTP, asJob for async, asListener for events. |
| Full Adoption | Migrate all HTTP routes to action classes. | Replace Route::post('articles', ArticleController::class) → Route::post('articles', PublishArticle::class). |
| Legacy | Wrap monolithic controllers in actions using asController. |
Example: class LegacyController extends Action { public function __invoke() { ... } } |
deleteWhenMissingModels, onQueue).asListener methods inherit event data seamlessly.asCommand integrates with Artisan, including IO components.Route::middleware().validate() helper or Form Requests in asController.ProcessPayment, GenerateReport).asJob for Async:
StoreArticle, UpdateUserProfile).asListener for event-driven workflows (e.g., SendWelcomeEmail).handle() method).handle(User $user)), reducing hidden couplings.run() → asJob → handle()).jobFailed) can log domain-specific errors.handle() inputs/outputs).class PublishArticle vs. ArticleController@store).handle() parameters/returns.PublishArticle::run(...)).handle()).How can I help you explore Laravel packages today?