{"id":14974663,"url":"https://github.com/safemood/laravel-workflow","last_synced_at":"2025-05-16T11:04:17.473Z","repository":{"id":248796395,"uuid":"824093849","full_name":"Safemood/laravel-workflow","owner":"Safemood","description":"Laravel package that simplifies workflows with clear actions definition and event tracking.","archived":false,"fork":false,"pushed_at":"2025-05-12T14:18:34.000Z","size":102,"stargazers_count":190,"open_issues_count":0,"forks_count":8,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-16T11:04:16.591Z","etag":null,"topics":["laravel","laravel-framework","laravel-package"],"latest_commit_sha":null,"homepage":"https://kbouzidi.com/payment-is-more-than-just-payment-laravel-workflow","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/Safemood.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":{"github":"Safemood"}},"created_at":"2024-07-04T10:53:33.000Z","updated_at":"2025-05-14T18:01:27.000Z","dependencies_parsed_at":"2024-08-19T09:05:44.551Z","dependency_job_id":"fead64dc-3cbb-449a-be56-90e00e6c9654","html_url":"https://github.com/Safemood/laravel-workflow","commit_stats":{"total_commits":84,"total_committers":3,"mean_commits":28.0,"dds":"0.30952380952380953","last_synced_commit":"71ee527211058584c736cb647ff77220334679fe"},"previous_names":["safemood/laravel-workflow"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Safemood%2Flaravel-workflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Safemood%2Flaravel-workflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Safemood%2Flaravel-workflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Safemood%2Flaravel-workflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Safemood","download_url":"https://codeload.github.com/Safemood/laravel-workflow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254518384,"owners_count":22084374,"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":["laravel","laravel-framework","laravel-package"],"created_at":"2024-09-24T13:50:53.005Z","updated_at":"2025-05-16T11:04:17.451Z","avatar_url":"https://github.com/Safemood.png","language":"PHP","funding_links":["https://github.com/sponsors/Safemood"],"categories":[],"sub_categories":[],"readme":"# Laravel Workflow\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/safemood/laravel-workflow?style=flat-square\u0026color=blue\n)](https://packagist.org/packages/safemood/laravel-workflow)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/safemood/laravel-workflow/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/safemood/laravel-workflow/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/safemood/laravel-workflow/fix-php-code-style-issues.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/safemood/laravel-workflow/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/safemood/laravel-workflow.svg?style=flat-square)](https://packagist.org/packages/safemood/laravel-workflow)\n\nLaravel Workflow combines feature details into one class, allowing for action definition and event tracking, simplifying understanding and revealing hidden logic.\n\n- [Laravel Workflow](#laravel-workflow)\n  - [Installation](#installation)\n  - [Create a Workflow](#create-a-workflow)\n  - [Create Actions](#create-actions)\n  - [Basic Example](#basic-example)\n    - [Define Workflow Logic](#define-workflow-logic)\n    - [Execute Workflow](#execute-workflow)\n  - [Conditional Action Execution](#conditional-action-execution)\n  - [Using DTO for Context](#using-dto-for-context)\n\n## Installation\n\nYou can install the package via Composer:\n\n```bash\ncomposer require safemood/laravel-workflow\n```\n\n## Create a Workflow\n\nYou can create a workflow using the artisan command:\n\n```bash\nphp artisan make:workflow PaymentWorkflow\n```\n\n## Create Actions\n\nYou can create an action using the artisan command:\n\n```bash\nphp artisan make:workflow-action ValidateCartItems\n```\n\n```php\n\u003c?php\n\nnamespace App\\Actions;\n\nuse Safemood\\Workflow\\Action;\nuse App\\DTO\\CartDTO;\n\nclass ValidateCartItems extends Action\n{\n    public function handle(CartDTO \u0026$context)\n    {\n        // Simulate extra validation logic\n        if (empty($context-\u003ecart)) {\n            throw new \\Exception('Cart is empty');\n        }\n\n       // you can pass data to the next action if you want\n\t  $context-\u003evalidated = true; \n        \n    }\n}\n```\n\n\n## Basic Example\n\nOnce you have set up your workflows and actions, you can define your business logic and orchestrate them within your Laravel application.\n\n### Define Workflow Logic\n\nIn your `PaymentWorkflow` class, you define the sequence of actions and conditions that make up your workflow:\n\n```php\n\u003c?php\n\nnamespace App\\Workflows;\n\nuse App\\Actions\\CalculateTotal;\nuse App\\Actions\\MakePayment;\nuse App\\Actions\\ValidateCartItems;\nuse App\\Events\\PaymentProcessed;\nuse App\\Jobs\\SendEmails;\nuse App\\Observers\\UserObserver;\nuse App\\Models\\Order;\nuse Safemood\\Workflow\\WorkflowManager;\n\nclass PaymentWorkflow extends WorkflowManager\n{\n    public function handle()\n    {\n        // Actions to be executed before the main action\n        $this-\u003eaddBeforeActions([\n            new ValidateCartItems(),\n            new CalculateTotal()\n        ]);\n\n        // The main action of the workflow\n        $this-\u003eaddMainAction(new MakePayment());\n\n        // Actions to be executed after the main action\n        $this-\u003eaddAfterAction(new SendEmails()); // Normal laravel Job in this example\n\n        // Observers to register for specific entities\n        $this-\u003eregisterObservers([\n            Order::class =\u003e OrderObserver::class,\n        ]);\n\n        // Good Debugging or if you want to understand what is happining during the workflow execution: \n\t  \n\t   $this-\u003etrackEvents([\n            PaymentProcessed::class\n        ]);\n\t  \n       // $this-\u003etrackAllEvents(); // or\n\n       // $this-\u003etrackEventsIn('App\\Events\\\\'); \n\n       \n    }\n}\n```\n\n### Execute Workflow\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Workflows\\PaymentWorkflow;\nuse Illuminate\\Http\\Request;\nuse App\\DTO\\CartDTO;\n\nclass PaymentController extends Controller\n{\n    public function payment(Request $request)\n    {\n         // Example context data representing a user's cart and user information\n        $context = new CartDTO(\n            [\n                ['id' =\u003e 1, 'name' =\u003e 'Product A', 'price' =\u003e 100, 'quantity' =\u003e 2],\n                ['id' =\u003e 2, 'name' =\u003e 'Product B', 'price' =\u003e 50, 'quantity' =\u003e 1]\n            ],\n            123\n        );\n\n        // Execute the PaymentWorkflow with the provided context\n        $paymentWorkflow = (new PaymentWorkflow)-\u003erun($context);\n\n        // Check if the workflow execution was successful\n        $success = $paymentWorkflow-\u003epasses();\n\n        // Check if the workflow execution failed\n        $failure = $paymentWorkflow-\u003efailed();\n\n        // Dump the workflow for debugging\n        // $paymentWorkflow-\u003edd();\n\n        // Handle the response based on the workflow outcome\n        if ($success) {\n            return $paymentWorkflow-\u003esuccessResponse();\n        }  \n\n        return $paymentWorkflow-\u003efailureResponse();\n    }\n}\n\n\n```\n\n## Conditional Action Execution\n\nYou can use the when method to conditionally execute an action.\n\n```php\n\u003c?php\n\nnamespace App\\Workflows;\n\nuse App\\Actions\\CalculateTotal;\nuse App\\Actions\\MakePayment;\nuse App\\Actions\\ValidateCartItems;\nuse App\\Actions\\SendEmailReceipt;\nuse Safemood\\Workflow\\WorkflowManager;\n\nclass PaymentWorkflow extends WorkflowManager\n{\n    public function handle()\n    {\n        $this-\u003ewhen(false, function () {\n            $this-\u003etrackAllEvents();\n        });\n\n        $this-\u003ewhen(true, function () {\n            $this-\u003eregisterObservers([\n                DummyModel::class =\u003e DummyModelObserver::class,\n            ]);\n        });\n\n        $this-\u003ewhen(true, function () {\n            $this-\u003eaddBeforeActions([\n                new DummyAction(),\n                new DummyAction(),\n            ]);\n        });\n\n        $this-\u003eunless(\n             value: false,\n             callback: fn () =\u003e $this-\u003etrackAllEvents(),\n             default: fn () =\u003e $this-\u003edoSomething()\n        );\n    }\n}\n```\n\n## Using DTO for Context  \n\nDTOInterface and BaseDTO allow you to handle context type-safely by using DTOs instead of raw arrays. Here's an example of defining a CartDTO class:\n\n```php\n\u003c?php\n\nnamespace App\\DTO;\n\nuse Safemood\\Workflow\\DTO\\BaseDTO;\n\nclass CartDTO extends BaseDTO\n{\n    public function __construct(\n        public array $cart,\n        public int $user_id,\n        public bool $validated = false\n    ) {}\n    // BaseDTO already implements the DTOInterface\n    // Automatically generates getter, setter, and toArray() methods\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsafemood%2Flaravel-workflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsafemood%2Flaravel-workflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsafemood%2Flaravel-workflow/lists"}