{"id":13828341,"url":"https://github.com/spatie/laravel-queueable-action","last_synced_at":"2025-05-14T00:04:51.671Z","repository":{"id":37733033,"uuid":"170877229","full_name":"spatie/laravel-queueable-action","owner":"spatie","description":"Queueable actions in Laravel","archived":false,"fork":false,"pushed_at":"2025-02-21T09:31:16.000Z","size":147,"stargazers_count":663,"open_issues_count":0,"forks_count":58,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-04-10T02:16:04.891Z","etag":null,"topics":["actions","laravel","queues"],"latest_commit_sha":null,"homepage":"https://spatie.be/open-source","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spatie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":"https://spatie.be/open-source/support-us"}},"created_at":"2019-02-15T14:26:00.000Z","updated_at":"2025-04-07T12:03:03.000Z","dependencies_parsed_at":"2025-01-14T22:43:49.902Z","dependency_job_id":"d8305a5d-f79c-4477-b713-46fec4b856a9","html_url":"https://github.com/spatie/laravel-queueable-action","commit_stats":{"total_commits":159,"total_committers":44,"mean_commits":"3.6136363636363638","dds":0.779874213836478,"last_synced_commit":"fdcfedaf30e250d9dabcf157a8c2f35eb8cddf79"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-queueable-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-queueable-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-queueable-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Flaravel-queueable-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spatie","download_url":"https://codeload.github.com/spatie/laravel-queueable-action/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254043309,"owners_count":22004923,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","laravel","queues"],"created_at":"2024-08-04T09:02:42.162Z","updated_at":"2025-05-14T00:04:51.650Z","avatar_url":"https://github.com/spatie.png","language":"PHP","funding_links":["https://spatie.be/open-source/support-us"],"categories":["PHP"],"sub_categories":[],"readme":"# Queueable actions in Laravel\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-queueable-action.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-queueable-action)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spatie/laravel-queueable-action/run-tests.yml?label=tests)\n![Check \u0026 fix styling](https://github.com/spatie/laravel-queueable-action/workflows/Check%20\u0026%20fix%20styling/badge.svg)\n[![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-queueable-action.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-queueable-action)\n\nActions are a way of structuring your business logic in Laravel.\nThis package adds easy support to make them queueable.\n\n```php\n$myAction-\u003eonQueue()-\u003eexecute();\n```\n\nYou can specify a queue name.\n\n```php\n$myAction-\u003eonQueue('my-favorite-queue')-\u003eexecute();\n```\n\n## Support us\n\n[\u003cimg src=\"https://github-ads.s3.eu-central-1.amazonaws.com/laravel-queueable-action.jpg?t=1\" width=\"419px\" /\u003e](https://spatie.be/github-ad-click/laravel-queueable-action)\n\nWe 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).\n\nWe 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).\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require spatie/laravel-queueable-action\n```\n\nYou can optionally publish the config file with:\n\n```bash\nphp artisan vendor:publish --provider=\"Spatie\\QueueableAction\\QueueableActionServiceProvider\" --tag=\"config\"\n```\n\nThis is the contents of the published config file:\n\n```php\nreturn [\n    /*\n     * The job class that will be dispatched.\n     * If you would like to change it and use your own job class,\n     * it must extends the \\Spatie\\QueueableAction\\ActionJob class.\n     */\n    'job_class' =\u003e \\Spatie\\QueueableAction\\ActionJob::class,\n];\n```\n\n## Usage\n\nIf you want to know about the reasoning behind actions and their asynchronous usage,\nyou should read the dedicated blog post: [https://stitcher.io/blog/laravel-queueable-actions](https://stitcher.io/blog/laravel-queueable-actions).\n\nYou can use the following Artisan command to generate queueable and synchronous action classes on the fly.\n\n```\nphp artisan make:action MyAction [--sync]\n```\n\nHere's an example of queueable actions in use:\n\n``` php\nclass MyAction\n{\n    use QueueableAction;\n\n    public function __construct(\n        OtherAction $otherAction,\n        ServiceFromTheContainer $service\n    ) {\n        // Constructor arguments can come from the container.\n\n        $this-\u003eotherAction = $otherAction;\n        $this-\u003eservice = $service;\n    }\n\n    public function execute(\n        MyModel $model,\n        RequestData $requestData\n    ) {\n        // The business logic goes here, this can be executed in an async job.\n    }\n}\n```\n\n```php\nclass MyController\n{\n    public function store(\n        MyRequest $request,\n        MyModel $model,\n        MyAction $action\n    ) {\n        $requestData = RequestData::fromRequest($myRequest);\n\n        // Execute the action on the queue:\n        $action-\u003eonQueue()-\u003eexecute($model, $requestData);\n\n        // Or right now:\n        $action-\u003eexecute($model, $requestData);\n    }\n}\n```\n\nThe package also supports actions using the `__invoke()` method. This will be detected automatically. Here is an example:\n\n``` php\nclass MyInvokeableAction\n{\n    use QueueableAction;\n\n    public function __invoke(\n        MyModel $model,\n        RequestData $requestData\n    ) {\n        // The business logic goes here, this can be executed in an async job.\n    }\n}\n```\n\nThe 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.\n\n```php\n$myInvokeableAction-\u003eonQueue()-\u003eexecute($model, $requestData);\n```\n\n### Testing queued actions\n\nThe package provides some test assertions in the `Spatie\\QueueableAction\\Testing\\QueueableActionFake` class. You can use them in a PhpUnit test like this:\n\n```php\n\n/** @test */\npublic function it_queues_an_action()\n{\n    Queue::fake();\n\n    (new DoSomethingAction)-\u003eonQueue()-\u003eexecute();\n\n    QueueableActionFake::assertPushed(DoSomethingAction::class);\n}\n```\n\nDon't forget to use `Queue::fake()` to mock Laravel's queues before using the `QueueableActionFake` assertions.\n\nThe following assertions are available:\n\n```php\nQueueableActionFake::assertPushed(string $actionClass);\nQueueableActionFake::assertPushedTimes(string $actionClass, int $times = 1);\nQueueableActionFake::assertNotPushed(string $actionClass);\nQueueableActionFake::assertPushedWithChain(string $actionClass, array $expextedActionChain = [])\nQueueableActionFake::assertPushedWithoutChain(string $actionClass)\n```\n\nFeel free to send a PR if you feel any of the other `QueueFake` assertions are missing.\n\n### Chaining actions\n\nYou can chain actions by wrapping them in the `ActionJob`.\n\nHere's an example of two actions with the same arguments:\n\n```php\nuse Spatie\\QueueableAction\\ActionJob;\n\n$args = [$userId, $data];\n\napp(MyAction::class)\n    -\u003eonQueue()\n    -\u003eexecute(...$args)\n    -\u003echain([\n        new ActionJob(AnotherAction::class, $args),\n    ]);\n```\n\nThe `ActionJob` takes the action class *or* instance as the first argument followed by an array of the action's own arguments.\n\n### Custom Tags\n\nIf you want to change what tags show up in Horizon for your custom actions you can override the `tags()` function.\n\n``` php\nclass CustomTagsAction\n{\n    use QueueableAction;\n\n    // ...\n\n    public function tags() {\n        return ['action', 'custom_tags'];\n    }\n}\n```\n\n### Job Middleware\n\nMiddleware where action job passes through can be added by overriding the `middleware()` function.\n\n``` php\nclass CustomTagsAction\n{\n    use QueueableAction;\n\n    // ...\n\n    public function middleware() {\n        return [new RateLimited()];\n    }\n}\n```\n\n### Action Backoff\n\nIf you would like to configure how many seconds Laravel should wait before retrying an action that has encountered\nan exception on a per-action basis, you may do so by defining a backoff property on your action class:\n\n``` php\nclass BackoffAction\n{\n    use QueueableAction;\n    \n    /**\n     * The number of seconds to wait before retrying the action.\n     *\n     * @var array\u003cint\u003e|int\n     */\n    public $backoff = 3;\n}\n```\n\nIf you require more complex logic for determining the action's backoff time, you may define a backoff method on your action class:\n\n``` php\nclass BackoffAction\n{\n    use QueueableAction;\n    \n    /**\n     * Calculate the number of seconds to wait before retrying the action.\n     *\n     */\n    public function backoff(): int\n    {\n        return 3;\n    }\n}\n```\n\nYou may easily configure \"exponential\" backoffs by returning an array of backoff values from the backoff method.\nIn 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:\n\n``` php\nclass BackoffAction\n{\n    /**\n     * Calculate the number of seconds to wait before retrying the action.\n     *\n     */\n    public function backoff(): array\n    {\n        return [1, 5, 10];\n    }\n}\n```\n\n### What is the difference between actions and jobs?\n\nIn short: constructor injection allows for much more flexibility.\nYou 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?!?).\n\n### Testing the package\n\n``` bash\ncomposer test\n```\n\n### Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.\n\n### Security\n\nIf you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker.\n\n## Credits\n\n- [Brent Roose](https://github.com/brendt)\n- [Alex Vanderbist](https://github.com/alexvanderbist)\n- [Sebastian De Deyne](https://github.com/sebdedeyne)\n- [Freek Van der Herten](https://github.com/freekmurze)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Flaravel-queueable-action","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspatie%2Flaravel-queueable-action","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Flaravel-queueable-action/lists"}