Open source March 2025 /12 pages
Laractions

Laractions

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() and retry(), or the $queue, $delay and $tries properties as defaults.
  • Arguments however you like them. Positional, named, or an associative array mapped to the handle() parameters by name.
  • Validation built in. A $rules array validates the resolved arguments before handle() 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, and trace() records who did what to which record.
  • Tooling. make:action generates classes, standalone or model scoped, and list:actions shows 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.