Коли додатку потрібно виконати послідовність кроків — одні з яких залежать один від одного, а інші можуть працювати паралельно — виникає спокуса запхати все в один клас або ланцюжок методів. Пакет Chevere Workflow пропонує чистіший підхід: ви оголошуєте завдання (jobs), налаштовуєте їхні залежності, а двигун автоматично визначає черговість виконання.
# Встановлення
composer require chevere/workflow
# Практичний приклад
Розглянемо процес реєстрації користувача, який має:
- Створити обліковий запис
- Надіслати привітальний лист
- Налаштувати безкоштовну пробну підписку
- Сповістити команду в Slack
Деякі кроки залежать від створення акаунту, інші ж можуть виконуватися паралельно після цього. Ручне керування цим процесом вимагає відстеження станів, написання допоміжного коду та обробки часткових збоїв. Workflow вирішує ці завдання декларативно.
# Побудова пайплайну
Ось як можна змоделювати процес онбордингу:
use function Chevere\Workflow\{workflow, sync, async, variable, response, run};
$workflow = workflow(
createAccount: sync(
CreateUserAccount::class,
name: variable('name'),
email: variable('email'),
password: variable('password'),
),
sendWelcomeEmail: async(
SendWelcomeEmail::class,
userId: response('createAccount', 'id'),
email: response('createAccount', 'email'),
),
createTrial: sync(
CreateTrialSubscription::class,
userId: response('createAccount', 'id'),
)->withRunIf(variable('enableTrial')),
notifyTeam: async(
NotifySlackChannel::class,
userEmail: response('createAccount', 'email'),
),
);
Кілька важливих моментів:
sync()блокує виконання до завершення завдання;async()запускається паралельно, щойно будуть готові всі залежності.variable('name')— це плейсхолдер для значення, яке ви передаєте під час виконання.response('createAccount', 'id')посилається на полеidіз результату крокуcreateAccount.->withRunIf(variable('enableTrial'))робить запускcreateTrialумовним — крок ігнорується, якщоenableTrialмає значення false.
Двигун будує граф залежностей на основі цих оголошень. Оскільки sendWelcomeEmail та notifyTeam залежать лише від createAccount, вони запустяться одночасно, щойно акаунт буде створено.
# Визначення завдання (Job)
Кожне завдання може бути замиканням (closure), класом, що викликається (invocable), або класом, який розширює Action від Chevere. Ось приклад простого завдання:
use Chevere\Action\Action;
class CreateUserAccount extends Action
{
public function __invoke(
string $name,
string $email,
string $password,
): array {
$user = User::create([
'name' => $name,
'email' => $email,
'password' => bcrypt($password),
]);
return [
'id' => $user->id,
'email' => $user->email,
];
}
}
Результат виконання стає відповіддю завдання. Наступні кроки можуть звертатися до окремих полів через response('createAccount', 'id') або до всієї відповіді через response('createAccount').
# Запуск Workflow
Передайте змінні безпосередньо в run() і отримайте результат будь-якого завдання:
$result = run(
$workflow,
name: 'Jane Doe',
email: 'jane@example.com',
password: 'secret',
enableTrial: true,
);
$userId = $result->response('createAccount')->int('id');
# Обробка помилок
Якщо завдання видає помилку, Workflow огортає її у WorkflowException, що містить інформацію про те, яке саме завдання дало збій і чому:
use Chevere\Workflow\Exceptions\WorkflowException;
try {
$result = run($workflow, ...);
} catch (WorkflowException $e) {
logger()->error("Job '{$e->name}' failed", [
'error' => $e->throwable->getMessage(),
]);
}
# Повторні спроби (Retries)
Для завдань, що працюють із зовнішніми сервісами, можна налаштувати політику повторів за допомогою withRetry():
notifyTeam: async(
NotifySlackChannel::class,
userEmail: response('createAccount', 'email'),
)->withRetry(timeout: 60, maxAttempts: 3, delay: 5),
# Інтеграція з Laravel
Спеціальний пакет забезпечує першокласну підтримку Laravel, додаючи Artisan-команди, базовий клас AbstractWorkflow та фасад для запуску воркфлоу.
composer require chevere/workflow-laravel
Створіть клас воркфлоу через Artisan:
php artisan make:workflow UserOnboarding
Потім опишіть логіку, використовуючи ті самі завдання:
use Chevere\WorkflowLaravel\AbstractWorkflow;
use Chevere\Workflow\Interfaces\WorkflowInterface;
use function Chevere\Workflow\{workflow, sync, async, variable, response};
class UserOnboarding extends AbstractWorkflow
{
protected function definition(): WorkflowInterface
{
return workflow(
createAccount: sync(
CreateUserAccount::class,
name: variable('name'),
email: variable('email'),
password: variable('password'),
),
sendWelcomeEmail: async(
SendWelcomeEmail::class,
userId: response('createAccount', 'id'),
email: response('createAccount', 'email'),
),
createTrial: sync(
CreateTrialSubscription::class,
userId: response('createAccount', 'id'),
)->withRunIf(variable('enableTrial')),
notifyTeam: async(
NotifySlackChannel::class,
userEmail: response('createAccount', 'email'),
),
);
}
}
Запускайте його через фасад Workflow будь-де у вашому додатку:
use Chevere\WorkflowLaravel\Facades\Workflow;
$result = Workflow::run(UserOnboarding::class,
name: $request->name,
email: $request->email,
password: $request->password,
enableTrial: $request->boolean('enable_trial'),
);
$userId = $result->response('createAccount')->int('id');
Сервіс-контейнер Laravel автоматично обробляє впровадження залежностей (dependency injection) для завдань на основі класів.
Ви також можете переглянути список усіх зареєстрованих воркфлоу за допомогою php artisan workflow:list або запустити їх прямо з термінала через php artisan workflow:run.
# Візуалізація графа
Для VS Code є офіційне розширення, яке рендерить ваш воркфлоу у вигляді діаграми Mermaid. Вона показує завдання як вузли та зв'язки між ними, включно з потоками даних. Оскільки граф будується безпосередньо з коду, він завжди залишається актуальним при будь-яких змінах у логіці.
# Підсумок
Chevere Workflow структурує багатоетапні процеси, які інакше могли б розсіятися по всьому проєкту або перетворити один метод на некерований код. Декларативний стиль дозволяє чітко бачити послідовність дій, а автоматична побудова графа забезпечує паралельне виконання без зайвих налаштувань.
Пакет також містить інструменти для тестування, що дозволяє перевіряти кожне завдання ізольовано та підтверджувати правильність усього графа виконання.
Більше деталей, включно з Workflow Providers та розширенням для VS Code, можна знайти в репозиторії Chevere Workflow на GitHub.