Skip to content

Commit 5fe96de

Browse files
committed
minor #21386 [Workflow] Document backed enum support (tucksaun)
This PR was merged into the 7.4 branch. Discussion ---------- [Workflow] Document backed enum support Fixes #21385 Fixes #21377 `@lyrixx`, I took the liberty of fixing #21377 at the same time, as I believe it makes sense as a whole. Your review on the semantic configuration is welcome :) Commits ------- 570d633 [Workflow] Document backed enum support
2 parents f710171 + 570d633 commit 5fe96de

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed

workflow.rst

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,154 @@ what actions are allowed on a blog post::
294294
// See a specific available transition for the post in the current state
295295
$transition = $workflow->getEnabledTransition($post, 'publish');
296296

297+
.. tip::
298+
299+
In some specific cases, using PHP enums as places in your workflows might
300+
make sense and one can use them seamlessly with the Workflow component if
301+
they uses backed enumerations.
302+
303+
.. versionadded:: 7.4
304+
305+
The support for PHP Backed enumerations as Workflow places was
306+
introduced with Symfony 7.4.
307+
308+
First, define your enum with backed values::
309+
310+
// src/Enumeration/BlogPostStatus.php
311+
namespace App\Enumeration;
312+
313+
enum BlogPostStatus: string
314+
{
315+
case Draft = 'draft';
316+
case Reviewed = 'reviewed';
317+
case Published = 'published';
318+
case Rejected = 'rejected';
319+
}
320+
321+
Then configure the workflow using the enum cases as places, initial
322+
marking, and transitions:
323+
324+
.. configuration-block::
325+
326+
.. code-block:: yaml
327+
328+
# config/packages/workflow.yaml
329+
framework:
330+
workflows:
331+
blog_publishing:
332+
type: 'workflow'
333+
marking_store:
334+
type: 'method'
335+
property: 'status'
336+
supports:
337+
- App\Entity\BlogPost
338+
initial_marking: !php/enum App\Enumeration\BlogPostStatus::Draft
339+
places: !php/enum App\Enumeration\BlogPostStatus
340+
transitions:
341+
to_review:
342+
from: !php/enum App\Enumeration\BlogPostStatus::Draft
343+
to: !php/enum App\Enumeration\BlogPostStatus::Reviewed
344+
publish:
345+
from: !php/enum App\Enumeration\BlogPostStatus::Reviewed
346+
to: !php/enum App\Enumeration\BlogPostStatus::Published
347+
reject:
348+
from: !php/enum App\Enumeration\BlogPostStatus::Reviewed
349+
to: !php/enum App\Enumeration\BlogPostStatus::Rejected
350+
351+
.. code-block:: xml
352+
353+
<!-- config/packages/workflow.xml -->
354+
<?xml version="1.0" encoding="UTF-8" ?>
355+
<container xmlns="http://symfony.com/schema/dic/services"
356+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
357+
xmlns:framework="http://symfony.com/schema/dic/symfony"
358+
xsi:schemaLocation="http://symfony.com/schema/dic/services
359+
https://symfony.com/schema/dic/services/services-1.0.xsd
360+
http://symfony.com/schema/dic/symfony
361+
https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
362+
363+
<framework:config>
364+
<!-- or type="state_machine" -->
365+
<framework:workflow name="blog_publishing" type="workflow" places="App\Enumeration\BlogPostStatus::*">
366+
<framework:marking-store type="single_state">
367+
<framework:argument>status</framework:argument>
368+
</framework:marking-store>
369+
<framework:support>App\Entity\BlogPost</framework:support>
370+
<framework:initial-marking>draft</framework:initial-marking>
371+
372+
<framework:transition name="to_review">
373+
<framework:from>draft</framework:from>
374+
<framework:to>reviewed</framework:to>
375+
</framework:transition>
376+
<framework:transition name="publish">
377+
<framework:from>reviewed</framework:from>
378+
<framework:to>published</framework:to>
379+
</framework:transition>
380+
<framework:transition name="reject">
381+
<framework:from>reviewed</framework:from>
382+
<framework:to>rejected</framework:to>
383+
</framework:transition>
384+
</framework:workflow>
385+
</framework:config>
386+
</container>
387+
388+
.. code-block:: php
389+
390+
// config/packages/workflow.php
391+
use App\Entity\BlogPost;
392+
use App\Enumeration\BlogPostStatus;
393+
use Symfony\Config\FrameworkConfig;
394+
395+
return static function (FrameworkConfig $framework): void {
396+
$blogPublishing = $framework->workflows()->workflows('blog_publishing');
397+
$blogPublishing
398+
->type('workflow')
399+
->supports([BlogPost::class])
400+
->initialMarking([BlogPostStatus::Draft]);
401+
402+
$blogPublishing->markingStore()
403+
->type('method')
404+
->property('status');
405+
406+
$blogPublishing->places(BlogPostStatus::cases());
407+
408+
$blogPublishing->transition()
409+
->name('to_review')
410+
->from(BlogPostStatus::Draft)
411+
->to([BlogPostStatus::Reviewed]);
412+
413+
$blogPublishing->transition()
414+
->name('publish')
415+
->from([BlogPostStatus::Reviewed])
416+
->to([BlogPostStatus::Published]);
417+
418+
$blogPublishing->transition()
419+
->name('reject')
420+
->from([BlogPostStatus::Reviewed])
421+
->to([BlogPostStatus::Rejected]);
422+
};
423+
424+
The component will now transparently cast the enum to its backing value
425+
when needed and vice-versa when working with your objects::
426+
427+
// src/Entity/BlogPost.php
428+
namespace App\Entity;
429+
430+
class BlogPost
431+
{
432+
private BlogPostStatus $status;
433+
434+
public function getStatus(): BlogPostStatus
435+
{
436+
return $this->status;
437+
}
438+
439+
public function setStatus(BlogPostStatus $status): void
440+
{
441+
$this->status = $status;
442+
}
443+
}
444+
297445
Using a multiple state marking store
298446
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299447

0 commit comments

Comments
 (0)