Download the PHP package djsharman/state without Composer
On this page you can find all versions of the php package djsharman/state. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download djsharman/state
More information about djsharman/state
Files in djsharman/state
Package state
Short Description The State design pattern. Implemented in PHP and with style.
License
Informations about the package state
Changes added by Darren Sharman
This is a State machine generator based on the work of Sebastian Bergmann (thank you Sebastian).
The intent of the State design pattern is to "allow an object to alter its behavior when its internal state changes. The object will appear to change its class". The State pattern can be used, for instance, to implement a Finite State Machine efficiently and elegantly. This approach can be useful when implementing business processes or workflows.
This version differs from the original in the following ways:
- You can regenerate your state machines whenever you like without losing your code (See below for how to do this).
-
You can now generate multiple state machines at once by using different .xml files. You can configure the output directory in the configuration files.
-
It favours convention over configuration so some of the configuration file options have been removed.
-
The generated classes are now namespaced so you can use your PSR autoloaders.
-
The state classes it generates have two additional methods onEnterState and onExitState. These are called automatically when the state machine enters or leaves a state. I'm guessing you worked that out for yourself though ;-)
-
The state machine passes a pointer to the main state machine instance along to each state as the state is instantiated. This means a state can modify the state machines state. $this->SM->{operation function name}(); e.g. $this->SM->close() from the Door example.
-
The visualizer now bases its output on the configuration file for the state machine rather than trying to generate this from the code.
-
The visualizer now tags the state transistion arrows with the name of the state change operation.
-
The tests that are generated might be broken, I haven’t got around to testing them yet.
- Examples Updated - In the examples folder you will find the Door example from Sebastian generated with the new code. There is also a bigger real world example of a state machine I created using this code to to with handling phone calls. The real code has been removed here, but the main structure of the statemachine is there for you to take a look at. You can see how crazy the diagrams generated can get when the statemachines get bigger.
Making sure your code doesn’t get overwritten
When you modify one of the functions generated by the generator be sure to move the code between the
and
comments. For an example please see onEnterState (source) function in the StartUpState.php file in the PwrCall example folder.
Implementing the generator to work with your existing code
You need to create one or more XML file to represent your state machine(s). The full XML state machine configuration is covered below. Importantly you should set the target directory targetdir where the statemachines are to be generated. This is a path relative to where you run the generator from. Also you should set the namespace that the statemachine classes will use.
You should then create a shell script (or batch file) to call the generator and, optionally, the visualizer.
The generator and visualiser take a single parameter which is the directory containing the state machine XML definition(s).
Example: Door
Consider a class Door
that represents a door. A door can be in one of three
states: open, closed, locked. When a Door
object receives messages (such as
open()
, close()
, lock()
, or unlock()
) from other objects, it responds
differently depending on its current state. For example, the effect of an
open()
message depends on whether the door is in its closed state or not (a
locked door has to be unlocked before it can be opened, for instance). The State
pattern describes how a Door
object can exhibit different behavior in each
state. The key idea in this pattern is to introduce classes to represent the
states of the door.
DoorState
The DoorState
interface (source) declares an
interface common to all classes that represent different states.
AbstractDoorState
The AbstractDoorState
class (source)
implements the operations required by the DoorState
interface in such a way
that all methods raise an IllegalStateTransitionException
by default.
OpenDoorState, ClosedDoorState, and LockedDoorState
OpenDoorState
(source),
ClosedDoorState
(source),
and LockedDoorState
(source) are child
classes of AbstractDoorState
that overwrite the open()
, close()
, lock()
,
and unlock()
methods appropriately to return the object that represents the
new state. OpenDoorState::close()
returns an instance of ClosedDoorState
,
for instance:
Door
The Door
class (source) maintains a state object (an
instance of a subclass of AbstractDoorState
) that represents the current
state of the door:
The Door
class forwards all state-specific messages to this state object.
Whenever the door changes state, the Door
object changes the state object it
uses.
Usage Example
The example script above yields the output below:
bool(true)
bool(true)
bool(true)
Fatal error: Uncaught exception 'IllegalStateTransitionException' in AbstractDoorState.php:25
Stack trace:
#0 Door.php(35): AbstractDoorState->lock()
#1 example.php(13): Door->lock()
#2 {main}
thrown in AbstractDoorState.php on line 25
Generating the State Machine
Using a code generator, the code shown above can be automatically generated from an XML specification such as the one shown below:
Some parts of the state machine configuration are assumed by convention.
- The name of the statemachine is taken from the name of the XML configuration file
- State tests are always the a given state name prefixed by "is". e.g. the test for OpenDoorState will be isOpenDoorState();
- Operation names in tests are always prefixed "testCan" or "testCannot". e.g. for the OpenDoorTest testCannotOpen and testCanClose.
Visualizing the State Machine
A graphical visualization of the statemachine states and its transitions can be generated based on the state machine's XML specification.
The runViz.php
(source) generates representation of the state machine as a directed graph
in Dot markup.
Documenting the State Machine through Tests
Using PHPUnit's TestDox functionality we can automatically generate documentation for the state machine based on its tests:
OpenDoor
[x] Can be closed
[x] Cannot be opened
[x] Cannot be locked
[x] Cannot be unlocked
ClosedDoor
[x] Cannot be closed
[x] Can be opened
[x] Can be locked
[x] Cannot be unlocked
LockedDoor
[x] Cannot be closed
[x] Cannot be opened
[x] Cannot be locked
[x] Can be unlocked
This automatically generated checklist makes it clear which transitions are allowed between the three states of the state machine.
All versions of state with dependencies
sebastian/finder-facade Version *
djsharman/libraries Version *
phpunit/php-token-stream Version *
theseer/fdomdocument Version *
phpunit/phpunit Version 5.0.*