Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 49 additions & 15 deletions workflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -327,26 +327,31 @@
Accessing the Workflow in a Class
---------------------------------

You can use the workflow inside a class by using
:doc:`service autowiring </service_container/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;

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) {
// ...
Expand All @@ -355,28 +360,27 @@
}
}

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 <autowiring-multiple-implementations-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.
Expand All @@ -402,6 +406,36 @@
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 <service-locator_autowire-locator>` attribute to
inject several workflows into the same class::

Check failure on line 413 in workflow.rst

View workflow job for this annotation

GitHub Actions / Lint (DOCtor-RST)

Please reorder the use statements alphabetically

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 <workflow_using-events>`
can help you simplify shared logic.

.. _workflow_using-events:

Using Events
Expand Down