PHPackages                             spatie/laravel-queueable-action - 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. [Queues &amp; Workers](/categories/queues)
4. /
5. spatie/laravel-queueable-action

ActiveLibrary[Queues &amp; Workers](/categories/queues)

spatie/laravel-queueable-action
===============================

Queueable action support in Laravel

2.17.0(2mo ago)6993.3M↑16.1%5414MITPHPPHP ^8.0CI passing

Since Feb 15Pushed 2mo ago9 watchersCompare

[ Source](https://github.com/spatie/laravel-queueable-action)[ Packagist](https://packagist.org/packages/spatie/laravel-queueable-action)[ Docs](https://github.com/spatie/laravel-queueable-action)[ Fund](https://spatie.be/open-source/support-us)[ RSS](/packages/spatie-laravel-queueable-action/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (5)Versions (43)Used By (14)

Queueable actions in Laravel
============================

[](#queueable-actions-in-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/f25a5056f4b63a8e01e6d040ccaccef426643044e27134521b129cc1a5e80edc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6c61726176656c2d717565756561626c652d616374696f6e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-queueable-action)[![GitHub Workflow Status](https://camo.githubusercontent.com/ad2c91929652700b515ce1b2b4fec6de7c47923b1e4cf2d21985f32ea038f870/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7370617469652f6c61726176656c2d717565756561626c652d616374696f6e2f72756e2d74657374732e796d6c3f6c6162656c3d7465737473)](https://camo.githubusercontent.com/ad2c91929652700b515ce1b2b4fec6de7c47923b1e4cf2d21985f32ea038f870/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7370617469652f6c61726176656c2d717565756561626c652d616374696f6e2f72756e2d74657374732e796d6c3f6c6162656c3d7465737473)[![Check & fix styling](https://github.com/spatie/laravel-queueable-action/workflows/Check%20&%20fix%20styling/badge.svg)](https://github.com/spatie/laravel-queueable-action/workflows/Check%20&%20fix%20styling/badge.svg)[![Total Downloads](https://camo.githubusercontent.com/59bcf146ffc1319d2009bc2c964c2ecb38fd6abc8882232849f8a2cd7e59ddc8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6c61726176656c2d717565756561626c652d616374696f6e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-queueable-action)

Actions are a way of structuring your business logic in Laravel. This package adds easy support to make them queueable.

```
$myAction->onQueue()->execute();
```

You can specify a queue name.

```
$myAction->onQueue('my-favorite-queue')->execute();
```

Support us
----------

[](#support-us)

[![](https://camo.githubusercontent.com/831105c3852d6b33a9f4f89a3abe4abc61b2d60f448300133a8f317383001171/68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f6c61726176656c2d717565756561626c652d616374696f6e2e6a70673f743d31)](https://spatie.be/github-ad-click/laravel-queueable-action)

We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).

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

[](#installation)

You can install the package via composer:

```
composer require spatie/laravel-queueable-action
```

You can optionally publish the config file with:

```
php artisan vendor:publish --provider="Spatie\QueueableAction\QueueableActionServiceProvider" --tag="config"
```

This is the contents of the published config file:

```
return [
    /*
     * The job class that will be dispatched.
     * If you would like to change it and use your own job class,
     * it must extends the \Spatie\QueueableAction\ActionJob class.
     */
    'job_class' => \Spatie\QueueableAction\ActionJob::class,
];
```

Usage
-----

[](#usage)

If you want to know about the reasoning behind actions and their asynchronous usage, you should read the dedicated blog post: .

You can use the following Artisan command to generate queueable and synchronous action classes on the fly.

```
php artisan make:action MyAction [--sync]

```

Here's an example of queueable actions in use:

```
class MyAction
{
    use QueueableAction;

    public function __construct(
        OtherAction $otherAction,
        ServiceFromTheContainer $service
    ) {
        // Constructor arguments can come from the container.

        $this->otherAction = $otherAction;
        $this->service = $service;
    }

    public function execute(
        MyModel $model,
        RequestData $requestData
    ) {
        // The business logic goes here, this can be executed in an async job.
    }
}
```

```
class MyController
{
    public function store(
        MyRequest $request,
        MyModel $model,
        MyAction $action
    ) {
        $requestData = RequestData::fromRequest($myRequest);

        // Execute the action on the queue:
        $action->onQueue()->execute($model, $requestData);

        // Or right now:
        $action->execute($model, $requestData);
    }
}
```

The package also supports actions using the `__invoke()` method. This will be detected automatically. Here is an example:

```
class MyInvokeableAction
{
    use QueueableAction;

    public function __invoke(
        MyModel $model,
        RequestData $requestData
    ) {
        // The business logic goes here, this can be executed in an async job.
    }
}
```

The actions using the `__invoke()` method should be added to the queue the same way as explained in the examples above, by running the `execute()` method after the `onQueue()` method.

```
$myInvokeableAction->onQueue()->execute($model, $requestData);
```

### Testing queued actions

[](#testing-queued-actions)

The package provides some test assertions in the `Spatie\QueueableAction\Testing\QueueableActionFake` class. You can use them in a PhpUnit test like this:

```
/** @test */
public function it_queues_an_action()
{
    Queue::fake();

    (new DoSomethingAction)->onQueue()->execute();

    QueueableActionFake::assertPushed(DoSomethingAction::class);
}
```

Don't forget to use `Queue::fake()` to mock Laravel's queues before using the `QueueableActionFake` assertions.

The following assertions are available:

```
QueueableActionFake::assertPushed(string $actionClass);
QueueableActionFake::assertPushedTimes(string $actionClass, int $times = 1);
QueueableActionFake::assertNotPushed(string $actionClass);
QueueableActionFake::assertPushedWithChain(string $actionClass, array $expextedActionChain = [])
QueueableActionFake::assertPushedWithoutChain(string $actionClass)
```

Feel free to send a PR if you feel any of the other `QueueFake` assertions are missing.

### Chaining actions

[](#chaining-actions)

You can chain actions by wrapping them in the `ActionJob`.

Here's an example of two actions with the same arguments:

```
use Spatie\QueueableAction\ActionJob;

$args = [$userId, $data];

app(MyAction::class)
    ->onQueue()
    ->execute(...$args)
    ->chain([
        new ActionJob(AnotherAction::class, $args),
    ]);
```

The `ActionJob` takes the action class *or* instance as the first argument followed by an array of the action's own arguments.

### Custom Tags

[](#custom-tags)

If you want to change what tags show up in Horizon for your custom actions you can override the `tags()` function.

```
class CustomTagsAction
{
    use QueueableAction;

    // ...

    public function tags() {
        return ['action', 'custom_tags'];
    }
}
```

### Job Middleware

[](#job-middleware)

Middleware where action job passes through can be added by overriding the `middleware()` function.

```
class CustomTagsAction
{
    use QueueableAction;

    // ...

    public function middleware() {
        return [new RateLimited()];
    }
}
```

### Action Backoff

[](#action-backoff)

If you would like to configure how many seconds Laravel should wait before retrying an action that has encountered an exception on a per-action basis, you may do so by defining a backoff property on your action class:

```
class BackoffAction
{
    use QueueableAction;

    /**
     * The number of seconds to wait before retrying the action.
     *
     * @var array|int
     */
    public $backoff = 3;
}
```

If you require more complex logic for determining the action's backoff time, you may define a backoff method on your action class:

```
class BackoffAction
{
    use QueueableAction;

    /**
     * Calculate the number of seconds to wait before retrying the action.
     *
     */
    public function backoff(): int
    {
        return 3;
    }
}
```

You may easily configure "exponential" backoffs by returning an array of backoff values from the backoff method. In this example, the retry delay will be 1 second for the first retry, 5 seconds for the second retry, and 10 seconds for the third retry:

```
class BackoffAction
{
    /**
     * Calculate the number of seconds to wait before retrying the action.
     *
     */
    public function backoff(): array
    {
        return [1, 5, 10];
    }
}
```

### What is the difference between actions and jobs?

[](#what-is-the-difference-between-actions-and-jobs)

In short: constructor injection allows for much more flexibility. You can read an in-depth explanation here: [https://stitcher.io/blog/laravel-queueable-actions](https://stitcher.io/blog/laravel-queueable-actions#what's-the-difference-with-jobs?!?).

### Testing the package

[](#testing-the-package)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.

### Security

[](#security)

If you've found a bug regarding security please mail  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Brent Roose](https://github.com/brendt)
- [Alex Vanderbist](https://github.com/alexvanderbist)
- [Sebastian De Deyne](https://github.com/sebdedeyne)
- [Freek Van der Herten](https://github.com/freekmurze)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

70

—

ExcellentBetter than 100% of packages

Maintenance83

Actively maintained with recent releases

Popularity65

Solid adoption and visibility

Community39

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor3

3 contributors hold 50%+ of commits

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 ~64 days

Recently: every ~181 days

Total

41

Last Release

86d ago

Major Versions

0.0.2 → 1.0.02019-02-28

1.0.0 → 2.0.02019-06-14

PHP version history (4 changes)0.0.1PHP ^7.2

2.9.0PHP ^7.2|^8.0

2.11.0PHP ^7.4|^8.0

2.13.0PHP ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7535935?v=4)[Spatie](/maintainers/spatie)[@spatie](https://github.com/spatie)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (76 commits)")[![brendt](https://avatars.githubusercontent.com/u/6905297?v=4)](https://github.com/brendt "brendt (31 commits)")[![rubenvanassche](https://avatars.githubusercontent.com/u/619804?v=4)](https://github.com/rubenvanassche "rubenvanassche (19 commits)")[![pactode](https://avatars.githubusercontent.com/u/5956778?v=4)](https://github.com/pactode "pactode (11 commits)")[![ryancco](https://avatars.githubusercontent.com/u/20148569?v=4)](https://github.com/ryancco "ryancco (10 commits)")[![alexmanase](https://avatars.githubusercontent.com/u/10696975?v=4)](https://github.com/alexmanase "alexmanase (9 commits)")[![AdrianMrn](https://avatars.githubusercontent.com/u/12762044?v=4)](https://github.com/AdrianMrn "AdrianMrn (7 commits)")[![AlexVanderbist](https://avatars.githubusercontent.com/u/6287961?v=4)](https://github.com/AlexVanderbist "AlexVanderbist (7 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (6 commits)")[![ricventu](https://avatars.githubusercontent.com/u/3369838?v=4)](https://github.com/ricventu "ricventu (4 commits)")[![nathanheffley](https://avatars.githubusercontent.com/u/8952123?v=4)](https://github.com/nathanheffley "nathanheffley (3 commits)")[![MatanYadaev](https://avatars.githubusercontent.com/u/13586343?v=4)](https://github.com/MatanYadaev "MatanYadaev (3 commits)")[![michielkempen](https://avatars.githubusercontent.com/u/14795113?v=4)](https://github.com/michielkempen "michielkempen (3 commits)")[![njoguamos](https://avatars.githubusercontent.com/u/29255728?v=4)](https://github.com/njoguamos "njoguamos (3 commits)")[![rogervila](https://avatars.githubusercontent.com/u/6053012?v=4)](https://github.com/rogervila "rogervila (3 commits)")[![angeljqv](https://avatars.githubusercontent.com/u/79208641?v=4)](https://github.com/angeljqv "angeljqv (2 commits)")[![hxnk](https://avatars.githubusercontent.com/u/1008127?v=4)](https://github.com/hxnk "hxnk (2 commits)")[![huubvdw](https://avatars.githubusercontent.com/u/11613086?v=4)](https://github.com/huubvdw "huubvdw (2 commits)")[![stancl](https://avatars.githubusercontent.com/u/33033094?v=4)](https://github.com/stancl "stancl (2 commits)")[![mostafaznv](https://avatars.githubusercontent.com/u/7619687?v=4)](https://github.com/mostafaznv "mostafaznv (2 commits)")

---

Tags

actionslaravelqueuesspatielaravel-queueable-action

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/spatie-laravel-queueable-action/health.svg)

```
[![Health](https://phpackages.com/badges/spatie-laravel-queueable-action/health.svg)](https://phpackages.com/packages/spatie-laravel-queueable-action)
```

###  Alternatives

[spatie/async

Asynchronous and parallel PHP with the PCNTL extension

2.8k4.5M37](/packages/spatie-async)[spatie/laravel-rate-limited-job-middleware

A middleware that can rate limit jobs

3584.0M6](/packages/spatie-laravel-rate-limited-job-middleware)[spatie/laravel-failed-job-monitor

Get notified when a queued job fails

1.0k2.6M4](/packages/spatie-laravel-failed-job-monitor)[mpbarlow/laravel-queue-debouncer

A wrapper job for debouncing other queue jobs.

63714.4k1](/packages/mpbarlow-laravel-queue-debouncer)[spatie/laravel-interacts-with-payload

Add variables to the payloads of all jobs in a Laravel app

6779.4k](/packages/spatie-laravel-interacts-with-payload)[spatie/mailcoach

Self-host Mailcoach

4007.0k](/packages/spatie-mailcoach)

PHPackages © 2026

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