Laractions

Laractions gives every meaningful operation in your app its own class: one handle() method, called the same way from a controller, a console command or a test, and moved onto a queue by changing one word.
What is Laractions?
Laractions brings the action pattern to Laravel. An action is a small class that does one thing: send the welcome email, publish the listing, charge the invoice. It carries its own arguments, its own validation and its own queue settings, so the controller that calls it goes back to being a controller.
There is no separate "async action" class to write, and no job to maintain alongside it. The class you run inline is the class you queue:
SendWelcomeEmail::create()->run('user@example.com', 'Welcome'); // now, inline SendWelcomeEmail::create()->dispatch('user@example.com', 'Welcome'); // later, on a worker
dispatch() wraps the action in a queued job for you, and queue(), delay() and retry() configure it at the call site:
SendWelcomeEmail::create() ->queue('emails') ->delay(10) ->retry(5) ->dispatch('user@example.com', 'Welcome');
Actions belong to models
An action usually acts on a record. Add the HasActions trait to the model and it can run its own actions, by class or by a short key you register:
class User extends Model { use HasActions; protected array $actions = [ 'send_welcome' => SendWelcomeEmail::class, ]; } $user->action('send_welcome')->run(); $user->action(SendWelcomeEmail::class)->run(); // or by class, nothing to register $user->action('send_welcome')->dispatch(); // same call, queued
The model is injected into the action, so a plain protected User $user; property is all the wiring the action needs.
What you get
- Sync or async from the same class.
run()executes now,dispatch()queues, and nothing else about the action changes. - Queue control per call or per class.
queue(),delay()andretry(), or the$queue,$delayand$triesproperties as defaults. - Arguments however you like them. Positional, named, or an associative array mapped to the
handle()parameters by name. - Validation built in. A
$rulesarray validates the resolved arguments beforehandle()runs, whatever called it. - Model binding.
$model->action(...)injects the model into a typed property, and the queued job re-fetches it on the worker. - Actors and tracing. Any model becomes an actor with
IsActor, andtrace()records who did what to which record. - Tooling.
make:actiongenerates classes, standalone or model scoped, andlist:actionsshows every action in the app. - Testable. Actions are plain classes: build one and run it, or bind a double in the container to replace it everywhere it is created.
Requirements
PHP 8.2 or newer, and Laravel 11 or newer. The service provider is auto discovered, so installation is a single Composer command:
composer require edulazaro/laractions
Tracing is the one feature that needs a table, and the migration is published only if you want it.
LaraClaude integration
Laractions is supported by LaraClaude, a Laravel toolkit plugin for Claude Code. It ships two skills that work against your installed version of the package: /lc:generate-action scaffolds a new action and registers it on the matching model, and /lc:extract-action pulls the body of a controller or Livewire method into an action and replaces the original code with the call.