├── src
├── Contracts
│ ├── ProcessPayload.php
│ └── TaskContract.php
├── Providers
│ └── PackageServiceProvider.php
└── Process.php
├── phpstan.neon
├── phpunit.xml
├── LICENSE
├── pint.json
├── composer.json
└── README.md
/src/Contracts/ProcessPayload.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ./tests
6 |
7 |
8 |
9 |
10 |
11 | ./app
12 | ./src
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Process.php:
--------------------------------------------------------------------------------
1 | >
15 | */
16 | protected array $tasks = [];
17 |
18 | /**
19 | * @param ProcessPayload $payload
20 | * @return mixed
21 | */
22 | public function run(ProcessPayload $payload): mixed
23 | {
24 | return Pipeline::send(
25 | passable: $payload,
26 | )->through(
27 | pipes: $this->tasks,
28 | )->thenReturn();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Steve McDougall.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/pint.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "psr12",
3 | "rules": {
4 | "align_multiline_comment": true,
5 | "array_indentation": true,
6 | "array_syntax": true,
7 | "blank_line_after_namespace": true,
8 | "blank_line_after_opening_tag": true,
9 | "combine_consecutive_issets": true,
10 | "combine_consecutive_unsets": true,
11 | "concat_space": true,
12 | "declare_parentheses": true,
13 | "declare_strict_types": true,
14 | "explicit_string_variable": true,
15 | "final_class": true,
16 | "final_internal_class": false,
17 | "fully_qualified_strict_types": true,
18 | "global_namespace_import": {
19 | "import_classes": true,
20 | "import_constants": true,
21 | "import_functions": true
22 | },
23 | "is_null": true,
24 | "lambda_not_used_import": true,
25 | "logical_operators": true,
26 | "mb_str_functions": true,
27 | "method_chaining_indentation": true,
28 | "modernize_strpos": true,
29 | "new_with_braces": true,
30 | "no_empty_comment": true,
31 | "not_operator_with_space": true,
32 | "ordered_traits": true,
33 | "protected_to_private": true,
34 | "simplified_if_return": true,
35 | "strict_comparison": true,
36 | "ternary_to_null_coalescing": true,
37 | "trim_array_spaces": true,
38 | "use_arrow_functions": true,
39 | "void_return": true,
40 | "yoda_style": true
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "juststeveking/laravel-business-process",
3 | "description": "Laravel Business Process is a simple and clean way to run business process using a Laravel Pipeline, in a structured and type-safe way.",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "role": "Developer",
8 | "name": "Steve McDougall",
9 | "email": "juststevemcd@gmail.com",
10 | "homepage": "https://www.juststeveking.uk/"
11 | }
12 | ],
13 | "autoload": {
14 | "psr-4": {
15 | "JustSteveKing\\BusinessProcess\\": "src/"
16 | }
17 | },
18 | "autoload-dev": {
19 | "psr-4": {
20 | "JustSteveKing\\BusinessProcess\\Tests\\": "tests/"
21 | }
22 | },
23 | "require": {
24 | "php": "^8.2"
25 | },
26 | "require-dev": {
27 | "laravel/pint": "^1.9",
28 | "orchestra/testbench": "^8.5",
29 | "pestphp/pest": "^2.5.2",
30 | "phpstan/phpstan": "^1.10.14"
31 | },
32 | "scripts": {
33 | "pint": [
34 | "./vendor/bin/pint"
35 | ],
36 | "stan": [
37 | "./vendor/bin/phpstan analyse"
38 | ],
39 | "test": [
40 | "./vendor/bin/pest"
41 | ]
42 | },
43 | "extra": {
44 | "laravel": {
45 | "providers": [
46 | "JustSteveKing\\BusinessProcess\\Providers\\PackageServiceProvider"
47 | ]
48 | }
49 | },
50 | "config": {
51 | "sort-packages": true,
52 | "optimize-autoloader": true,
53 | "allow-plugins": {
54 | "pestphp/pest-plugin": true
55 | }
56 | },
57 | "minimum-stability": "dev",
58 | "prefer-stable": true
59 | }
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Business Process
2 |
3 |
4 | [![Latest Version][badge-release]][packagist]
5 | [![Software License][badge-license]][license]
6 | [](https://github.com/JustSteveKing/laravel-business-process/actions/workflows/tests.yml)
7 | [![PHP Version][badge-php]][php]
8 | [![Total Downloads][badge-downloads]][downloads]
9 |
10 | [badge-release]: https://img.shields.io/packagist/v/juststeveking/laravel-business-process.svg?style=flat-square&label=release
11 | [badge-license]: https://img.shields.io/packagist/l/juststeveking/laravel-business-process.svg?style=flat-square
12 | [badge-php]: https://img.shields.io/packagist/php-v/juststeveking/laravel-business-process.svg?style=flat-square
13 | [badge-downloads]: https://img.shields.io/packagist/dt/juststeveking/laravel-business-process.svg?style=flat-square&colorB=mediumvioletred
14 |
15 | [packagist]: https://packagist.org/packages/juststeveking/laravel-business-process
16 | [license]: https://github.com/juststeveking/laravel-business-process/blob/main/LICENSE
17 | [php]: https://php.net
18 | [downloads]: https://packagist.org/packages/juststeveking/laravel-business-process
19 |
20 |
21 | Laravel Business Process is a simple and clean way to run business process using a Laravel Pipeline, in a structured and type-safe way.
22 |
23 | This package is inspired by the tutorial I wrote for Laravel News [Going Past Actions in Laravel](https://laravel-news.com/going-past-actions-in-laravel).
24 |
25 | ## Installation
26 |
27 | ```shell
28 | composer require juststeveking/laravel-business-process
29 | ```
30 |
31 | ## Usage
32 |
33 | To get started with this package, all you need to do is create a new process class:
34 |
35 | ```php
36 | use JustSteveKing\BusinessProcess\Process;
37 |
38 | final class PurchaseProduct extends Process
39 | {
40 | protected array $tasks = [
41 | CheckStockLevel::class,
42 | ProcessOrder::class,
43 | DecreaseStockLevel::class,
44 | NotifyWarehouse::class,
45 | EmailCustomer::class,
46 | ];
47 | }
48 | ```
49 |
50 | Our process class registers the tasks that need to be completed for this process to run, each task must implement the `TaskContract` interface that comes with this package.
51 |
52 | ```php
53 | use JustSteveKing\BusinessProcess\Contracts\TaskContract;
54 |
55 | final class CheckStockLevel implements TaskContract
56 | {
57 | public function __invoke(ProcessPayload $payload, Closure $next): mixed
58 | {
59 | // perform your logic here with the passed in payload.
60 |
61 | return $next($payload);
62 | }
63 | }
64 | ```
65 |
66 | Your tasks are standard classes that the `Pipeline` class from Laravel would expect.
67 |
68 | The payload is a class that implements `ProcessPayload` interface, signalling that it is a payload for a process. They are simple plain old PHP classes with no requirements to add methods.
69 |
70 | ```php
71 | use JustSteveKing\BusinessProcess\Contracts\ProcessPayload;
72 |
73 | final class PurchaseProductPayload implements ProcessPayload
74 | {
75 | public function __construct(
76 | // add whatever public properties you need here
77 | public int $product,
78 | public int $user,
79 | public int $order,
80 | ) {}
81 | }
82 | ```
83 |
84 | Finally, we can call this process within our controller/job/cli wherever you need to.
85 |
86 | ```php
87 | final class PurchaseController
88 | {
89 | public function __construct(
90 | private readonly PurchaseProduct $process,
91 | ) {}
92 |
93 | public function __invoke(PurchaseRequest $request, int $product): JsonResponse
94 | {
95 | try {
96 | $this->process->run(
97 | payload: $request->payload(),
98 | );
99 | } catch (Throwable $exception) {
100 | // Handle exception
101 | }
102 |
103 | // return response.
104 | }
105 | }
106 | ```
107 | ## Testing
108 |
109 | To run the test:
110 |
111 | ```bash
112 | composer run test
113 | ```
114 |
115 | ## Credits
116 |
117 | - [Steve McDougall](https://github.com/JustSteveKing)
118 | - [All Contributors](../../contributors)
119 |
120 | ## LICENSE
121 |
122 | The MIT License (MIT). Please see [License File](./LICENSE) for more information.
123 |
124 |
--------------------------------------------------------------------------------