@@ -294,6 +294,154 @@ what actions are allowed on a blog post::
294
294
// See a specific available transition for the post in the current state
295
295
$transition = $workflow->getEnabledTransition($post, 'publish');
296
296
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
+
297
445
Using a multiple state marking store
298
446
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
299
447
0 commit comments