PHPackages                             edulazaro/laractions - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. edulazaro/laractions

ActiveLibrary[Framework](/categories/framework)

edulazaro/laractions
====================

Actions for Laravel

1.2.1(1w ago)0614↓41.7%1MITPHPPHP ^8.2

Since Mar 9Pushed 1w ago1 watchersCompare

[ Source](https://github.com/edulazaro/laractions)[ Packagist](https://packagist.org/packages/edulazaro/laractions)[ RSS](/packages/edulazaro-laractions/feed)WikiDiscussions main Synced yesterday

READMEChangelog (10)Dependencies (9)Versions (12)Used By (1)

[![Laractions](art/banner.png)](art/banner.png)

Laractions - Actions for Laravel
================================

[](#laractions---actions-for-laravel)

> Encapsulate your business logic into clean, reusable classes that run **synchronously or asynchronously** in Laravel.

 [![Total Downloads](https://camo.githubusercontent.com/21cf9f36304898186d715932fa6f2e39e4700fac358fa7b2f1b92db8077ef3e0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6564756c617a61726f2f6c6172616374696f6e73)](https://packagist.org/packages/edulazaro/laractions) [![Latest Stable Version](https://camo.githubusercontent.com/a7d4d6034f84528ebaa1afaef36d52f473ac7600178e0395727c4a4c16d18e95/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6564756c617a61726f2f6c6172616374696f6e73)](https://packagist.org/packages/edulazaro/laractions)

Introduction
------------

[](#introduction)

**Laractions** is a package that introduces an **action-based pattern** for Laravel applications. Actions encapsulate specific pieces of logic that can be executed synchronously or asynchronously, keeping your controllers and models clean.

Instead of placing business logic in controllers, models, or services, **actions** allow you to encapsulate reusable operations in self-contained classes.

✅ **Supports Standalone &amp; Model-Scoped Actions**
✅ **Allows Asynchronous Execution with Queues**
✅ **Provides an Artisan Generator for Quick Creation**

### Why Use Actions?

[](#why-use-actions)

Instead of bloating **controllers**, **models**, or **services**, Laractions keeps logic **encapsulated** and **reusable**.

FeatureLaractions**Encapsulation**Keeps business logic clean &amp; reusable**Async Execution**Supports Laravel queues &amp; retries**Validation**Auto-validates parameters before execution**Model-bound**Works directly with Eloquent models**Fluent API**`run()`, `dispatch()`, `retry()`, `queue()`---

Installation
------------

[](#installation)

Install via Composer:

```
composer require edulazaro/laractions
```

Once installed, the package will be available in your Laravel application.

Naming Convention
-----------------

[](#naming-convention)

Action class names drop the `Action` suffix because the `App\Actions\*` namespace already carries the intent — just like Laravel uses `App\Jobs\SendEmail` rather than `App\Jobs\SendEmailJob`. The `make:action` generator strips a trailing "Action" automatically, so both `php artisan make:action SendEmailAction` and `php artisan make:action SendEmail` produce the same `SendEmail` class.

Creating Actions
----------------

[](#creating-actions)

You can manually create an action or use the **artisan command**:

```
php artisan make:action SendEmail
```

This will generate this basic action:

```
namespace App\Actions;

use EduLazaro\Laractions\Action;

class SendEmail extends Action
{
    public function handle()
    {
        // Your action logic here
    }
}
```

You will place the logic inside the `handle` method:

```
namespace App\Actions;

use EduLazaro\Laractions\Action;

class SendEmail extends Action
{
    public function handle(string $email, string $subject, string $message)
    {
        // Your action logic here
    }
}
```

You can then run the action via the `run` method:

```
SendEmail::create()->run('user@example.com', 'Welcome!', 'Hello User');
```

### How `run()` maps arguments to `handle()`

[](#how-run-maps-arguments-to-handle)

`run()` forwards its arguments to `handle()` by reflection. You can call it in three ways:

```
// Positional
SendEmail::create()->run('user@example.com', 'Welcome!', 'Hello User');

// Named arguments
SendEmail::create()->run(email: 'user@example.com', subject: 'Welcome!', message: 'Hello User');

// Associative array, mapped to parameters by name
SendEmail::create()->run([
    'email' => 'user@example.com',
    'subject' => 'Welcome!',
    'message' => 'Hello User',
]);
```

When `handle()` declares **more than one parameter**, the keys of an associative array are matched to the parameter names (the last example above).

When `handle()` declares **a single `array` (or `iterable`/`mixed`/untyped) parameter**, the array is passed through whole as that one argument — the "attribute bag" pattern:

```
class CreateInvoice extends Action
{
    public function handle(array $attributes)
    {
        // $attributes === ['concept' => 'x', 'amount' => 10]
        return $attributes['concept'];
    }
}

CreateInvoice::create()->run(['concept' => 'x', 'amount' => 10]);
```

When the single parameter is a **concrete type** (an object or scalar, e.g. `handle(File $file)`), a single array is **not** treated as the bag: its keys are mapped by name, and a single value is passed positionally — so both of these bind `$file`:

```
ProcessFile::create()->run(['file' => $file]);  // mapped by name -> $file = $file
ProcessFile::create()->run($file);              // positional     -> $file = $file
```

This mirrors native PHP: an `array` parameter receives the array whole, while a typed parameter receives the matching value, never the wrapping array. (A union that includes `array`/`iterable` — e.g. `array|Foo` — still receives the bag.)

You can customize the constructor. Dependencies will be injected:

```
namespace App\Actions;

use EduLazaro\Laractions\Action;
use App\Services\MailerService;

class SendEmail extends Action
{
    protected MailerService $mailer;

    /**
     * Inject dependencies via the constructor.
     */
    public function __construct(MailerService $mailer)
    {
        $this->mailer = $mailer;
    }

    /**
     * Handle the action logic.
     */
    public function handle(string $email, string $subject, string $message)
    {
        // Use the injected service
        $this->mailer->send($email, $subject, $message);
    }
}
```

You can run the action as usually via the `run` method:

```
SendEmail::create()->run('user@example.com', 'Welcome!', 'Hello User');
```

Creating Model Actions
----------------------

[](#creating-model-actions)

You can manually create a model action or use the **artisan command**:

```
php artisan make:action SendEmail --model=User
```

This will create the next basic model action:

```
namespace App\Actions\User;

use EduLazaro\Laractions\Action;
use App\Models\User;

class SendEmail extends Action
{
    protected User $user;

    public function handle()
    {
        // Implement action logic for user here
    }
}
```

The user instance will be available inside the `$user` attribute.

Models using actios should use the `HasActions` trait, so you can register actions inside the `$actions` array of the model:

```
class User extends Model
{
    use HasActions;

    protected array $actions = [
        'send_email' => SendEmail::class,
    ];
}
```

Now, you can execute the action using:

```
$user->action('send_email')->run('user@example.com', 'Welcome!', 'Hello User');
```

Alternatively, you can still call the action class directly so you don't have to define the action inside the model:

```
$user->action(SendEmail::class)->run('user@example.com', 'Welcome!', 'Hello User');
```

Dynamic Parameters
------------------

[](#dynamic-parameters)

Laractions provides a flexible `with()` method to set action attributes dynamically:

```
$action = SendEmail::create()->with([
    'email' => 'user@example.com',
    'subject' => 'Welcome!',
    'message' => 'Hello User'
])->run();
```

This avoids passing long parameter lists in the `run()` method. Please note that these values will be set as action attributes, so you would access them via:

```
$this->email;
```

Actions and Models
------------------

[](#actions-and-models)

When calling an action from a model, the model is automatically injected into the action:

```
$user->action(SendEmail::class)->run();
```

If the `SendEmail` class has a `$user` property, the action will automatically set the model:

```
class SendEmail extends Action
{
    protected User $user; // Automatically injected

    public function handle()
    {
        Mail::to($this->user->email)->send(new WelcomeMail());
    }
}
```

Running Actions Asynchronously
------------------------------

[](#running-actions-asynchronously)

Laractions allows dispatching actions asynchronously as jobs:

```
$action = SendEmail::create()
    ->queue('high')
    ->delay(10)
    ->retry(5)
    ->dispatch('user@example.com', 'Welcome!', 'Hello User');
```

This queues the action instead of executing it immediately. The job will be automatically created and liked to the action, so you don't need to define it.

You can configure how actions are dispatched as jobs:

```
class SendEmail extends Action
{
    protected int $tries = 5;
    protected ?int $delay = 30;
    protected ?string $queue = 'emails';
}
```

Mocking Actions for Tests
-------------------------

[](#mocking-actions-for-tests)

During unit tests, you can **mock actions**:

```
$user->mockAction(SendEmail::class, new class {
    public function run()
    {
        return 'Mocked!';
    }
});

echo $user->action(SendEmail::class)->run(); // Output: 'Mocked!'
```

This allows testing without executing real logic.

List Available Actions
----------------------

[](#list-available-actions)

To list all registered actions in your application, run:

```
php artisan list:actions
```

Logging Actions
---------------

[](#logging-actions)

Enable logging for any action:

```
SendEmail::create()
    ->enableLogging()
    ->run('user@example.com', 'Welcome!', 'Hello User');
```

Logs will be written to Laravel's log files.

Acting as an Actor
------------------

[](#acting-as-an-actor)

You can make any model an actor (like a User) by using the `IsActor` trait:

```
use EduLazaro\Laractions\Concerns\IsActor;

class User extends Model
{
    use IsActor;
}
```

Then, call actions like this:

```
$user->act(SendInvoice::class)
     ->on($order)
     ->trace()
     ->run();
```

This automatically sets the actor on the action before executing it.

Enabling Tracing
----------------

[](#enabling-tracing)

Tracing is disabled by default. You can enable it per action like this:

```
SendEmail::create()
    ->trace()
    ->run('user@example.com', 'Welcome!', 'Hello!');
```

You can assign the actor and actionable model like so:

```
SendEmail::create()
    ->actor($user)
    ->on($targetModel)
    ->trace()
    ->run($params);
```

Here is an traced action started by an actor:

```
$user->act(SendInvoice::class)
     ->on($order)
     ->trace()
     ->run();
```

LaraClaude integration
----------------------

[](#laraclaude-integration)

Laractions is supported by [LaraClaude](https://github.com/edulazaro/laraclaude), a Laravel toolkit plugin for [Claude Code](https://claude.ai/code). It ships two skills that work with your actions:

```
/lc:generate-action Property/ToggleFeatured
/lc:extract-action PropertyController:store

```

- **`/lc:generate-action`** scaffolds a new action class with the right boilerplate and registers it on the corresponding model, following your project's [naming convention](#naming-convention).
- **`/lc:extract-action`** pulls business logic out of a controller or Livewire component method into a standalone action, and replaces the original code with the action call.

Both skills read the installed Laractions API so they only use what your version actually has, match the conventions of your existing actions, and run a syntax check on the generated class.

Install the plugin in Claude Code with `/plugin install github:edulazaro/laraclaude`.

Sponsors
--------

[](#sponsors)

Laractions is supported by the following sponsors. Thank you for keeping it growing:

 [![Kenodo](art/logo-kenodo.png)](https://kenodo.com) [Kenodo](https://kenodo.com) [![AndorraDev](art/logo-andorradev.png)](https://andorradev.com) [AndorraDev](https://andorradev.com)

Author
------

[](#author)

Created by [Edu Lazaro](https://edulazaro.com)

License
-------

[](#license)

Laractions is open-sourced software licensed under the [MIT license](LICENSE.md).

###  Health Score

48

—

FairBetter than 93% of packages

Maintenance98

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~46 days

Recently: every ~90 days

Total

11

Last Release

11d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6a3c47449dfb2ec121aa410da024f47586b87cc2799a825f0418e6c5e5904955?d=identicon)[edulazaro](/maintainers/edulazaro)

---

Top Contributors

[![edulazaro](https://avatars.githubusercontent.com/u/7797530?v=4)](https://github.com/edulazaro "edulazaro (20 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/edulazaro-laractions/health.svg)

```
[![Health](https://phpackages.com/badges/edulazaro-laractions/health.svg)](https://phpackages.com/packages/edulazaro-laractions)
```

###  Alternatives

[laravel/octane

Supercharge your Laravel application's performance.

4.0k26.6M223](/packages/laravel-octane)[unopim/unopim

UnoPim Laravel PIM

10.5k2.4k](/packages/unopim-unopim)[code16/sharp

Laravel Content Management Framework

79164.7k8](/packages/code16-sharp)[ecotone/laravel

Ecotone for Laravel — CQRS, Event Sourcing, Sagas, Durable Workflows, and Outbox on top of Laravel Queue, via PHP attributes.

21318.6k3](/packages/ecotone-laravel)[codewithdennis/larament

Larament is a time-saving starter kit to quickly launch Laravel 13.x projects. It includes FilamentPHP 5.x pre-installed and configured, along with additional tools and features to streamline your development workflow.

3891.8k](/packages/codewithdennis-larament)[r2luna/brain

Brain: A process-driven architecture alternative for your Laravel Application.

6338.7k1](/packages/r2luna-brain)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
