PHPackages                             gmorel/state-workflow-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. gmorel/state-workflow-bundle

ActiveSymfony-bundle[Utility &amp; Helpers](/categories/utility)

gmorel/state-workflow-bundle
============================

Helping you implementing a complex yet easily maintainable workflow

1.0.0(11y ago)54201MITPHPPHP &gt;=5.3.3

Since May 3Pushed 11y ago1 watchersCompare

[ Source](https://github.com/gmorel/StateWorkflowBundle)[ Packagist](https://packagist.org/packages/gmorel/state-workflow-bundle)[ RSS](/packages/gmorel-state-workflow-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (2)Versions (2)Used By (1)

[![StateWorkflowBundle logo](https://raw.githubusercontent.com/gmorel/StateWorkflowBundle/master/doc/StateWorkflowBundle-logo.png)](https://raw.githubusercontent.com/gmorel/StateWorkflowBundle/master/doc/StateWorkflowBundle-logo.png)

State Workflow Bundle ===================== [![Build Status](https://camo.githubusercontent.com/3661aca603c88cd19549fe2da68367c3a50a43bed6d621aeb409897097bc26e8/68747470733a2f2f7472617669732d63692e6f72672f676d6f72656c2f5374617465576f726b666c6f7742756e646c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/gmorel/StateWorkflowBundle)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/a459a204a91acfec10d1629696dae8492b9a0f57ef64da93b4dfbaac0cd68d1a/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f676d6f72656c2f5374617465576f726b666c6f7742756e646c652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/gmorel/StateWorkflowBundle/?branch=master)[![Code Coverage](https://camo.githubusercontent.com/698e916a94bd544aaa8af0cb49f2b046b74e4774d1ca2235bbd4c6c76a75d576/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f676d6f72656c2f5374617465576f726b666c6f7742756e646c652f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/gmorel/StateWorkflowBundle/?branch=master)[![Dependency Status](https://camo.githubusercontent.com/23718ab6c38da0257f650217eb234963be921a3e0659c3eea1ff8a50ea5ebd44/68747470733a2f2f7777772e76657273696f6e6579652e636f6d2f757365722f70726f6a656374732f3535343630626233356434663961343463363030303064332f62616467652e7376673f7374796c653d666c6174)](https://www.versioneye.com/user/projects/55460bb35d4f9a44c60000d3)[![Latest Stable Version](https://camo.githubusercontent.com/1bf8321d8533c940bab40ef56c47446311b4de52dc08358a0a6cdcf035de5c67/68747470733a2f2f706f7365722e707567782e6f72672f676d6f72656c2f73746174652d776f726b666c6f772d62756e646c652f762f737461626c652e737667)](https://packagist.org/packages/gmorel/state-workflow-bundle)[![License](https://camo.githubusercontent.com/39ea3c2e105fd30d0f05a4da4abf69a38247255b2642c8276bf0142030d47ed2/68747470733a2f2f706f7365722e707567782e6f72672f676d6f72656c2f73746174652d776f726b666c6f772d62756e646c652f6c6963656e7365)](https://packagist.org/packages/gmorel/state-workflow-bundle)

[![Symfony 2](https://raw.githubusercontent.com/spec-gen/state-workflow-spec-gen-bundle/master/doc/symfony.png)](https://raw.githubusercontent.com/spec-gen/state-workflow-spec-gen-bundle/master/doc/symfony.png)

Helping you implementing a complex yet easily maintainable workflow. --------------------------------------------- Keywords : State Design Pattern, Workflow, Finite State Machine, Symfony2

[![Workflow](https://raw.githubusercontent.com/gmorel/StateWorkflowBundle/master/doc/demo-booking-workflow.png "Workflow")](https://raw.githubusercontent.com/gmorel/StateWorkflowBundle/master/doc/demo-booking-workflow.png)

Our [StateWorkflow](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/StateWorkflow.php) object is responsible for managing all your `States` and their `Transitions` for your given `Entity` implementing [HasStateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/HasStateInterface.php#L9). Every single State is a class implementing our [StateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/StateInterface.php#L10-10) and is managing its own transitions.

### Ubiquitous Language

[](#ubiquitous-language)

- **State** : an Entity finite state at a given time (ex: `Booking payed`, `Quote cancelled`, etc..)
- **Transition** : a transition between state A and state B (ex: Booking waiting for payment --`Send confirmation mail`-&gt; Booking payed, etc..)

### Pros

[](#pros)

- All your workflow is described via classes
- Each State is responsible for **its own transitions**
- Each State Transition can **contain logic** (Log, Event Sourcing, Assertion, Send mail, etc..)
- States are Symfony2 services
- All your workflow can be easily **Unit Tested**
- Entity's current state can be easily stored in database (simple string)
- Workflow **specification file can be [generated](https://github.com/spec-gen/state-workflow-spec-gen-bundle) from code base**

### Cons

[](#cons)

- Each time you add a transition you have to modify your [own](https://github.com/gmorel/StateWorkflowDemo/blob/master/src/BookingEngine/Domain/State/BookingStateInterface.php#L44-44) interface extending our [StateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/StateInterface.php#L10-10) implementation
- If you only need a Finite State Machine without logic in your transitions. You might prefer
- Not really following the famous precept : "prefer composition over inheritance" ..

\### Usage

```
$bookingWorkflow = $this->get('demo.booking_engine.state_workflow');

// Initialize entity state to booking workflow default state : incomplete
// `Booking::__construct` contains `$bookingWorkflow->getDefaultState()->initialize($this);`
$booking = new Booking($bookingWorkflow, 200);

// Set incomplete Booking as paid
// Take care of the state transition (incomplete -> paid) - Send confirmation mail
$booking->getState($bookingWorkflow)
    ->setBookingAsPaid($booking);

// Get current booking state : StatePaid
$currentState = $booking->getState($bookingWorkflow);
```

With this Service declarations

```

    Booking Workflow
    demo.booking_engine.state_workflow

```

### Implementation example

[](#implementation-example)

Booking Demo

### Details

[](#details)

It will allow you to manage `States` and especially their available `Transitions` for an `Entity` (for example a Booking class) implementing our interface [HasStateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/HasStateInterface.php#L9-9). It is aiming at helping implementing a complex `Workflow` where each `State` implementing our interface [StateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/StateInterface.php#L10-10) is responsible for its `Transitions` (methods) to other `States`. Some `Transitions` being impossible (not part of your `Workflow`) and then throwing the exception [UnsupportedStateTransitionException](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/Exception/UnsupportedStateTransitionException.php#L9-9) whenever called.

Each `State` has a [Symfony2 service](http://symfony.com/doc/current/book/service_container.html#what-is-a-service) [tag](http://symfony.com/doc/current/book/service_container.html#tags):

```

```

This way you will be able to manage available `States` for different `Entities` by using other [Symfony2 tags](http://symfony.com/doc/current/book/service_container.html#tags) since Booking, Content and Customer entities shall not share the same `Workflow`/`States`). You will then need to modify the [Symfony2 CompilerPass](http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html) in order to let your `Workflow` be aware of its `States`.

#### Adding new State:

[](#adding-new-state)

In case you wish to add a new `State` you will need to create a new Class implementing our interface [StateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/StateInterface.php#L10-10).

#### Adding new Transition:

[](#adding-new-transition)

In case you wish to add a new `Transition` you will need to add a new method in your [XXXStateInterface](https://github.com/gmorel/StateWorkflowDemo/blob/master/src/BookingEngine/Domain/State/BookingStateInterface.php#L44-44) extending our [StateInterface](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/StateInterface.php#L10-10). You can also use our helper [AbstractState](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/AbstractState.php#L15-15) which would implement default behavior ie. a method throwing our [UnsupportedStateTransitionException](https://github.com/gmorel/StateWorkflowBundle/blob/master/StateEngine/Exception/UnsupportedStateTransitionException.php#L9-9).

#### Installation

[](#installation)

##### Step 1: Download the Bundle

[](#step-1-download-the-bundle)

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

```
$ composer require gmorel/state-workflow-bundle "~1.0"
```

This command requires you to have Composer installed globally, as explained in the [installation chapter](https://getcomposer.org/doc/00-intro.md)of the Composer documentation.

##### Step 2: Enable the Bundle

[](#step-2-enable-the-bundle)

Then, enable the bundle by adding the following line in the `app/AppKernel.php`file of your project:

```
