kphoen / doctrine-state-machine-bundle
Integrates DoctrineStateMachineBehavior in Symfony2.
Installs: 217 553
Dependents: 0
Suggesters: 0
Security: 0
Stars: 48
Watchers: 3
Forks: 19
Open Issues: 7
Type:symfony-bundle
Requires
- doctrine/doctrine-bundle: ~1.2
- kphoen/doctrine-state-machine: ~1.0
- symfony/framework-bundle: ~2.3|~3.0
Requires (Dev)
- symfony/console: ~2.3|~3.0
- symfony/twig-bundle: ~2.3|~3.0
Suggests
- alom/graphviz: To generate Graphviz views of state machines
- symfony/console: To execute the command to generate Graphviz views of state machines
- symfony/twig-bundle: To integrate with Twig
This package is auto-updated.
Last update: 2022-02-01 12:27:45 UTC
README
Doctrine2 behavior adding a finite state machine in your entities.
The state machine implementation used is Finite.
Status
This project is DEPRECATED and should NOT be used.
If someone magically appears and wants to maintain this project, I'll gladly give access to this repository.
Configuration
In your app/config/config.yml
file, define your state machines:
k_phoen_doctrine_state_machine: auto_injection: true # should we automatically inject state machines into hydrated objects? auto_validation: true # should we validate any status change before the persistence happens? state_machines: article_state_machine: class: \Acme\FooBundle\Entity\Article property: state states: new: {type: initial} reviewed: ~ accepted: ~ published: {type: final, properties: {printable: true}} rejected: {type: final} transitions: review: {from: [new], to: reviewed} accept: {from: [reviewed], to: accepted} publish: {from: [accepted], to: published} reject: {from: [new, reviewed, accepted, published], to: rejected}
The state machines configuration is pretty straightforward. In addition to the states and transitions, you just have to define the entity class and the column used to store the state.
Important: the entity has to implement the Stateful
interface.
To ease the implementation, you can use the StatefulTrait
that comes bundled
with the behavior.
Usage
Stateful
entities have access to their own state machine. See Finite's
documentation for more details about it.
The Article
entity below is ready to be used as a Stateful
entity.
<?php namespace Acme\FooBundle\Entity; use KPhoen\DoctrineStateMachineBehavior\Entity\Stateful; use KPhoen\DoctrineStateMachineBehavior\Entity\StatefulTrait; class Article implements Stateful { use StatefulTrait; /** * define your fields here */ /** * @var string */ protected $state = 'new'; /** * Set state * * @param string $state * @return Article */ public function setState($state) { $this->state = $state; return $this; } /** * Get state * * @return string */ public function getState() { return $this->state; } /** * Sets the object state. * Used by the StateMachine behavior * * @return string */ public function getFiniteState() { return $this->getState(); } /** * Sets the object state. * Used by the StateMachine behavior * * @param string $state */ public function setFiniteState($state) { return $this->setState($state); } }
Entities using the StatefulTrait
see the setStateMachine()
and
getStateMachine()
methods implemented and gain access to the following
methods:
can($transition)
: indicating if the given transition is allowed ;- and a few magic methods, based on the transition allowed by the
state-machine:
{TransitionName}()
: apply the transition {TransitionName} (ie:accept()
,reject()
, etc) ;can{TransitionName}()
: test if the transition {TransitionName} can be applied (ie:canAccept()
,canReject()
, etc).is{StateName}()
: test if the current state is {StatusName} (ie:isAccepted()
,isRejected()
, etc).
<?php $article = new Article(); $article->canAccept(); $article->canReject(); $article->can('accept'); $article->accept(); $article->publish(); $article->isAccepted(); $article->isRejected();
Lifecyle callbacks
If you use the event-aware state-machine (which is the default one used by the bundle), the extension provides a listener implementing "lifecyle callbacks" for stateful entities.
For each available transition, three methods can be executed:
pre{TransitionName}()
: called before the transition {TransitionName} is applied ;post{TransitionName}()
: called after the transition {TransitionName} is applied ;can{TransitionName}()
: called when the state-machine tests if the transition {TransitionName} can be applied.
<?php namespace Acme\FooBundle\Entity; use KPhoen\DoctrineStateMachineBehavior\Entity\Stateful; use KPhoen\DoctrineStateMachineBehavior\Entity\StatefulTrait; class Article implements Stateful { // previous code public function preAccept() { // your logic here } public function postAccept() { // your logic here } public function onCanAccept() { // your logic here } }
Using a service
You can put the state logic outside of the entity using a listener on Finite events. The extension provides an abstract EventSubcriber with the same methods as the "lifecyle callbacks" listener.
You need to declare a service and extend the AbstractSubcriber.
services: article_workflow_subscriber: class: Acme\FooBundle\Workflow\ArticleSubscriber tags: - { name: kernel.event_subscriber }
<?php namespace Acme\FooBundle\Workflow; use KPhoen\DoctrineStateMachineBundle\Listener\AbstractSubscriber; class ArticleSubscriber extends AbstractSubscriber { public function supportsObject($object) { return $object instanceof \Acme\FooBundle\Entity\Article; } public function preAccept() { // your logic here } public function postAccept() { // your logic here } public function canAccept() { // your logic here } }
Twig
The bundle also exposes a few Twig helpers:
{# your template ... #} {% if article|can('reject') %} <a class="btn btn-danger" href="{{ path('article_delete', article) }}"> <i class="icon-trash"></i> {{ 'link_reject'|trans }} </a> {% endif %} {# this is strictly equivalent #} {% if can(article, 'reject') %} <a class="btn btn-danger" href="{{ path('article_delete', article) }}"> <i class="icon-trash"></i> {{ 'link_reject'|trans }} </a> {% endif %} {% if current_state(article).isFinal %} blabla {% endif %} {% if article|is_status('rejected') %} blabla {% endif %} {# this is strictly equivalent #} {% if is_status(article, 'rejected') %} blabla {% endif %} {% if article|has_property('printable') %} {{ article|property('printable') ? 'I can print' : 'I CANNOT print' }} {% endif %} {# this is strictly equivalent #} {% if has_property(article, 'printable') %} {{ property(article, 'printable') ? 'I can print' : 'I CANNOT print' }} {% endif %}
Installation
Install the behavior adding kphoen/doctrine-state-machine-bundle
to your composer.json or from CLI:
composer require kphoen/doctrine-state-machine-bundle
Than register the bundle in your app/AppKernel.php
file:
// app/AppKernel.php public function registerBundles() { $bundles = array( // ... new KPhoen\DoctrineStateMachineBundle\KPhoenDoctrineStateMachineBundle(), // ... ); }
License
This bundle is released under the MIT license.