Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Action Laravel Package

bekwoh/laravel-action

bekwoh/laravel-action is a lightweight package that brings a clean action pattern to Laravel. Encapsulate business logic in reusable, single-purpose action classes, keep controllers thin, and make workflows easier to test, compose, and maintain across your application. Simple to install and integrat...

View on GitHub
Deep Wiki
Context7

Getting Started

This release (2.3.0) is a compatibility release: Laravel 13 support, PHPUnit 12, Pest 4. There are no new APIs to learn, so onboarding is still about adopting the action pattern rather than the package plumbing.

  • Install and pin deliberately. composer require cleaniquecoders/laravel-action then check the resolved illuminate/* constraint in composer.lock. The package now allows ^13.0, which means a careless composer update on a Laravel 11/12 app can still resolve fine — but if you are on Laravel 11, confirm the lower bound before assuming you are covered.
  • Look first at the package's own test suite (tests/) rather than the README. Action packages tend to have thin docs and the tests are the real contract for how handle(), asJob(), and dependency injection are expected to behave.
  • Where to look in your app: create app/Actions/. That directory is the single place a reviewer should be able to open and understand every business operation that is not a controller, model, or job.
  • First use case: take one controller method that does three or more things (validate → create model → fire event/notify → return response) and move the middle into a single action. Call it from the controller and from an artisan command in the same week. If both call sites read cleanly, the pattern is earning its place.

Implementation Patterns

Controller as a thin adapter. Controllers validate and delegate; the action owns the transaction and the side effects.

// app/Http/Controllers/RegisterController.php
public function store(RegisterRequest $request)
{
    $user = RegisterUserAction::run($request->validated());

    return redirect()->route('dashboard');
}

Compose small actions, don't build god-actions. Actions calling actions is the natural extension point, and it is the main reason to use the pattern at all. Keep each action to roughly one reason to change; if you find yourself injecting six services, split it.

Queue the same class you call synchronously. The highest-leverage use of an action package is that the identical code path runs inline in a request and async in a worker. Wrap anything slow (PDF generation, third-party syncs, mail fan-out) and switch it to queued dispatch without forking the logic. Test both paths — a class that works inline and explodes in a worker is the most common failure here.

Inject collaborators via the constructor, pass input via the method. Services, repositories, and clocks belong in the constructor (resolved by the container); request data, IDs, and DTOs belong in the method signature. Mixing the two makes actions untestable and unserializable.

Return typed results, not void. Have actions return a model, a DTO, or an explicit result object. This keeps call sites honest and gives you something to assert in tests. Actions returning bool are a smell — the caller ends up re-querying for state it should have received.

Integration tips for this release:

  • Use the action as the boundary for database transactions. DB::transaction() inside the action, not in the controller, so the queued path gets the same guarantees.
  • Dispatch domain events from the action, not the controller — then queued execution emits them too.
  • In tests, bind fake collaborators into the container and resolve the action, or call it statically if the package supports it. Prefer container resolution in tests; it exercises the same wiring production uses.
  • Wire actions into console commands and scheduled tasks. A command that is a one-liner calling an action is a good sign your actions are properly scoped.

Gotchas and Tips

  • The CI matrix moved to Laravel 12 + PHP 8.4/8.3. If your app is on PHP 8.2, this package version may still install (the constraint is on illuminate/*, not php), but you are outside what upstream tests. Check the package's composer.json require.php before upgrading, and treat PHP 8.3 as the practical floor for a smooth ride.
  • PHPUnit 12 / Pest 4 are dev-only changes — but they leak into your workflow if you copy the package's phpunit.xml.dist. PHPUnit 12 dropped and renamed several configuration attributes and deprecated a batch of assertions. Do not wholesale-copy the updated dist file into an app on PHPUnit 10/11; it will fail to parse or silently ignore settings. Cherry-pick.
  • Laravel 13 support does not mean Laravel 13 semantics. Framework majors routinely change container resolution, queue serialization, and event dispatch order. Verify queued actions round-trip (serialize/unserialize) on the framework version you actually run before relying on them in production.
  • Constructor injection is the classic debugging trap. A queued action is serialized; any collaborator you injected must be serializable, or the job fails at dispatch time with an unhelpful "Serialization of 'Closure' is not allowed" error. Inject contracts that the container can rebuild, or resolve inside handle().
  • Debugging queued actions: log the action class name and the input payload at the top of handle(). When three actions compose into one job, stack traces lose the originating request. A correlation ID passed into the action pays for itself the first time something fails at 2am.
  • Don't let app/Actions become a junk drawer. Adopt a naming convention (VerbNounAction) and a rule that an action has exactly one public entry point. Actions with multiple public methods get called inconsistently and turn into service classes with worse names.
  • Extension points to check before forking: base-class hooks (before/after handling, prepare()-style methods), the job wrapper used for queued dispatch, and any config file. If you need retry/backoff/queue-name control, confirm whether the package exposes it or whether you must override the job class — this is where teams end up vendoring the package.
  • Pin the release. "cleaniquecoders/laravel-action": "^2.3" and commit the lock file. A compatibility release like this one is safe, but the next minor could tighten the PHP floor.
  • Not worth upgrading for on its own if you are on Laravel 11/12 and PHP 8.2: nothing here changes runtime behavior. Upgrade opportunistically alongside your framework bump, and run your action tests against both the inline and queued paths when you do.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource