diff --git a/workflow.rst b/workflow.rst index 45e9a41b75b..38a8c412a40 100644 --- a/workflow.rst +++ b/workflow.rst @@ -327,10 +327,16 @@ if you are using Doctrine, the matching column definition should use the type `` Accessing the Workflow in a Class --------------------------------- -You can use the workflow inside a class by using -:doc:`service autowiring ` and using -``camelCased workflow name + Workflow`` as parameter name. If it is a state -machine type, use ``camelCased workflow name + StateMachine``:: +Symfony creates a service for each workflow you define. You have two ways of +injecting each workflow in any service or controller: + +**(1) Use a specific argument name** + +Type-hint your construtor/method argument with ``WorkflowInterface`` and name the +argument using this pattern: "workflow name in camelCase" + ``Workflow`` suffix. +If it is a state machine type, use the ``StateMachine`` suffix. + +For example, to inject the ``blog_publishing`` workflow defined earlier:: use App\Entity\BlogPost; use Symfony\Component\Workflow\WorkflowInterface; @@ -338,15 +344,14 @@ machine type, use ``camelCased workflow name + StateMachine``:: class MyClass { public function __construct( - // Symfony will inject the 'blog_publishing' workflow configured before private WorkflowInterface $blogPublishingWorkflow, ) { } public function toReview(BlogPost $post): void { - // Update the currentState on the post try { + // update the currentState on the post $this->blogPublishingWorkflow->apply($post, 'to_review'); } catch (LogicException $exception) { // ... @@ -355,28 +360,27 @@ machine type, use ``camelCased workflow name + StateMachine``:: } } -Workflows can also be injected thanks to their name and the -:class:`Symfony\\Component\\DependencyInjection\\Attribute\\Target` -attribute:: +**(2) Use the ``#[Target]`` attribute** + +When :ref:`dealing with multiple implementations of the same type ` +the ``#[Target]`` attribute helps you select which one to inject. Symfony creates +a target with the same name as each workflow. + +For example, to select the ``blog_publishing`` lock defined earlier:: - use App\Entity\BlogPost; use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\Workflow\WorkflowInterface; class MyClass { public function __construct( - #[Target('blog_publishing')] - private WorkflowInterface $workflow + #[Target('blog_publishing')] private WorkflowInterface $workflow, ) { } // ... } -This allows you to decorrelate the argument name of any implementation -name. - .. versionadded:: 6.2 All workflows and state machines services are tagged since in Symfony 6.2. @@ -402,6 +406,36 @@ name. You can find the list of available workflow services with the ``php bin/console debug:autowiring workflow`` command. +Injecting Multiple Workflows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use the :ref:`AutowireLocator ` attribute to +inject several workflows into the same class:: + + use Symfony\Component\DependencyInjection\ServiceLocator; + use Symfony\Component\DependencyInjection\Attribute\AutowireLocator; + + class MyClass + { + public function __construct( + #[AutowireLocator('blog_publishing', 'user_registration')] + private ServiceLocator $workflows, + ) { + } + + public function someMethod(): void + { + $workflow = $this->workflows->get('user_registration'); + + // ... + } + } + +.. tip:: + + Injecting multiple workflows into your :ref:`workflow listeners ` + can help you simplify shared logic. + .. _workflow_using-events: Using Events