lorisleiva/laravel-actions
Laravel Actions lets you write one PHP class that handles a single task and run it as a controller, job, listener, command, or plain object—cutting boilerplate and helping you focus on what your application actually does rather than which files to create.
make:action scaffolding, and a community of prior art at near-zero licensing cost.::run), invokable controller, queued job, event listener, and artisan command. This directly supports the roadmap decision "should this be a job or a controller?" being deferred — you can start synchronous and promote the same class to a queued job without rewriting business logic. That's a measurable reduction in rework when a feature graduates from MVP to scale.Action::mock()), and the package ships a PHPStan extension (v2.11.0) plus IDE autocomplete fixes. This supports a roadmap commitment to raising static-analysis levels or shortening the path from feature spec to tested unit.app/Actions), which matters if the roadmap includes scaling the engineering team or opening the codebase to more squads.ShouldDispatchAfterCommit), idempotent/unique queued work (ShouldBeUnique support, debounced jobs in v2.13.0), and unified attribute handling with validation (WithAttributes).Consider adoption when:
make:action scaffolding reduce the need for internal architecture docs.App namespace are resolvable, which matters for modular/multi-package codebases.Look elsewhere when:
asJob argument prepending, unified attributes) can make stack traces and queue payloads less obvious than an explicit Job class, which slows incident response.dependents: 0 signal in the package metadata — almost certainly a data-collection artifact rather than a genuine absence of consumers, but treat it as an unverified assumption and do your own reference-checking before citing ecosystem adoption as a justification.For executives (one paragraph): Laravel Actions is a free, MIT-licensed convention that lets one class describe one business capability and run it as an API endpoint, a background job, an event listener, or a CLI command without rewriting it. The business case is rework avoidance: features that start as simple endpoints frequently need to become queued or scheduled later, and today that means a second implementation and a second set of tests. It also gives us a single answer to "where does this code live," which shortens code review and onboarding as the team grows. Risk is low — it's a pattern, not a platform, with no data lock-in, a permissive license, and active maintenance through Laravel 13. Cost is adoption effort, not procurement.
For engineering leadership: The pitch is consistency plus testability, not novelty. We get a documented, opinionated structure for business logic, scaffolding via make:action, first-class mocking for unit tests, a PHPStan extension, and Octane-safe internals. We should adopt it as an explicit, enforced standard in a bounded area (new feature work) and measure it: time-to-first-commit on new features, count of duplicated job/controller pairs eliminated, and static-analysis level over two quarters. Mitigations: pin the version, gate upgrades behind our Laravel upgrade cadence, and keep the escape hatch explicit — if the abstraction ever fights us, action classes remain plain PHP and the trait is removable.
For the engineering team: This is a tool for deferring an irreversible decision. You write the business logic once in handle(), and the asController / asJob / asListener / asCommand methods are thin adapters. You can ship synchronous today and promote to a queued job with a decorator, without touching handle(). It comes with test mocking and a PHPStan extension. The tradeoff is honest: it's an abstraction, decorators add indirection in stack traces, and the pattern only works if we actually follow it — so we adopt it as a standard in new code, not as an optional extra.
How can I help you explore Laravel packages today?