SlideShare a Scribd company logo
1 of 90
Download to read offline
A SHORT TALE ABOUT


STATE MACHINE
Once upon a time…
Kelly
final class Payment


{


private bool $pending = false;


}
Th
e end of chapter 1
A few days later
final class Payment


{


private bool $pending = false;


private bool $failed = false;


}
final class Payment


{


private bool $pending = false;


private bool $failed = false;


}
final class Payment


{


public const NEW = 1;


public const PENDING = 2;


public const FAILED = 3;


private int $state = self::NEW;


}
?
State Machine
(Q, Σ, δ, q0, F)


Q = a
fi
nite set of states


Σ = a
fi
nite, nonempty input alphabet


δ = a series of transition functions


q0 = the starting state


F = the set of accepting states
NEW
PENDING
FAILED PAID
Create
Pay
Fail
Let’s do the research!
De
fi
ne possible states and relation between them


Protect business rules


Integrate other services on transitions
What do we expect?
WinzouStateMachine
Callback’s execution in con
fi
g
fi
le


Used heavily in Sylius


Con
fi
gurable arguments of service


Services have to be public in order to integrate them with state machine


Without stable release, yet battle-tested and robust
$config =
[

'graph' => 'payment'
,

'property_path' => 'state'
,

'states' => ['new','pending','failed','paid']
,

'transitions' =>
[

'process' =>
[

'from' => ['new']
,

'to' => 'pending'
,

]
,

'fail' =>
[

'from' => ['pending']
,

'to' => 'failed'
,

]
,

'pay' =>
[

'from' => ['pending']
,

'to' => 'paid'
,

]
,

]
,

];
$config =
[

'graph' => 'payment'
,

'property_path' => 'state'
,

'states' => ['new','pending','failed','paid'],
'transitions' =>
[

'process' =>
[

'from' => ['new']
,

'to' => 'pending'
,

]
,

'fail' =>
[

'from' => ['pending']
,

'to' => 'failed'
,

]
,

'pay' =>
[

'from' => ['pending']
,

'to' => 'paid'
,

]
,

]
,

];
$config =
[

'graph' => 'payment'
,

'property_path' => 'state',
'states' => ['new','pending','failed','paid']
,

'transitions' => [
'process' =>
[

'from' => ['new']
,

'to' => 'pending'
,

]
,

'fail' =>
[

'from' => ['pending']
,

'to' => 'failed'
,

]
,

'pay' =>
[

'from' => ['pending']
,

'to' => 'paid'
,

]
,

]
,

];
$config =
[

'graph' => 'payment'
,

'property_path' => 'state'
,

'states' => ['new','pending','failed','paid'],
'transitions' =>
[

'process' =>
[

'from' => ['new']
,

'to' => 'pending'
,

]
,

'fail' =>
[

'from' => ['pending']
,

'to' => 'failed'
,

]
,

'pay' =>
[

'from' => ['pending']
,

'to' => 'paid'
,

]
,

]
,

];
Symfony Work
fl
ow
Maintained by Symfony


Flex support


Work
fl
ow & state machine support


Execution of external services with events


XML / YAML / PHP support out-of-the-box


Best documentation hands down
$definitionBuilder = new DefinitionBuilder()
;

$definition = $definitionBuilder->addPlaces(['new','pending','failed','paid']
)

->addTransition(new Transition('process', 'new', 'pending')
)

->addTransition(new Transition('fail', [‘pending'], 'failed')
)

->addTransition(new Transition('pay', 'pending', 'paid')
)

->build(
)

;

$singleState = true
;

$property = 'state'
;

$marking = new MethodMarkingStore($singleState, $property)
;

$workflow = new Workflow($definition, $marking, null, 'payment');
$definitionBuilder = new DefinitionBuilder()
;

$definition = $definitionBuilder->addPlaces(['new','pending','failed','paid']
)

->addTransition(new Transition('process', 'new', 'pending')
)

->addTransition(new Transition('fail', ['pending'], 'failed')
)

->addTransition(new Transition('pay', 'pending', 'paid')
)

->build(
)

;

$singleState = true
;

$property = 'state'
;

$marking = new MethodMarkingStore($singleState, $property)
;

$workflow = new Workflow($definition, $marking, null, 'payment');
$definitionBuilder = new DefinitionBuilder()
;

$definition = $definitionBuilder->addPlaces(['new','pending','failed','paid']
)

->addTransition(new Transition('process', 'new', 'pending')
)

->addTransition(new Transition('fail', [‘pending'], 'failed')
)

->addTransition(new Transition('pay', 'pending', 'paid')
)

->build(
)

;

$singleState = true
;

$property = 'state'
;

$marking = new MethodMarkingStore($singleState, $property)
;

$workflow = new Workflow($definition, $marking, null, 'payment');
Finite
Oldest and most popular implementation


(in terms of stars)


Least used implementation


(in terms of daily installs according to packagist)


Extendability with events & callbacks de
fi
nition


Perhaps reached its EOL


(https://github.com/yohang/Finite/issues/161)


It is said to be little bit heavier implementation compared to Winzou
Back to
the
st
ory…
final class Payment


{


public const NEW = 'new';


private string $state = self::NEW;


public function getState(): string


{


return $this->state;


}


public function setState(string $state): void


{


$this->state = $state


}


}
WinzouStateMachine
$payment = new Payment()
;

$stateMachine = new StateMachine($payment, $config)
;

$stateMachine->apply('process')
;

$stateMachine->apply('fail');
Symfony Work
fl
ow
$payment = new Payment()
;

$workflow->apply($payment, 'process')
;

$workflow->apply($payment, 'fail');
Th
e end of chapter 2
New adventur
e
WinzouStateMachine
final class InventoryOperato
r

{

public function __invoke(TransitionEvent $transitionEvent): voi
d

{

$stateMachine = $transitionEvent->getStateMachine()
;

/** @var Payment $payment *
/

$payment = $stateMachine->getObject()
;

// Reduce inventory of bought product
s

}

}
$config =
[

// ..
.

'callbacks' =>
[

'before' =>
[

'reduce_amount' =>
[

'on' => ['pay']
,

'do' => new InventoryOperator()
,

]
,

]
,

]
,

];
final class InventoryOperato
r

{

public function __invoke(TransitionEvent $transitionEvent): voi
d

{

$stateMachine = $transitionEvent->getStateMachine()
;

/** @var Payment $payment *
/

$payment = $stateMachine->getObject()
;

// Reduce inventory of bought product
s

}

}
$config =
[

// ..
.

'callbacks' =>
[

'before' =>
[

'reduce_amount' =>
[

'on' => ['pay']
,

'do' => new InventoryOperator()
,

]
,

]
,

]
,

];
final class InventoryOperato
r

{

public function __invoke(TransitionEvent $transitionEvent): voi
d

{

$stateMachine = $transitionEvent->getStateMachine()
;

/** @var Payment $payment *
/

$payment = $stateMachine->getObject()
;

// Reduce inventory of bought product
s

}

}
$config =
[

// ..
.

'callbacks' => [
'before' => [
'reduce_amount' =>
[

'on' => ['pay']
,

'do' => new InventoryOperator()
,

]
,

]
,

]
,

];
Guard


Before


After
Callbacks types
* Same can be achieved with dispatched events
class StateMachine implements StateMachineInterface


{


public function apply(/** */): void


{


// Guard callback


if (!$this->can($transition)) {


throw new SMException();


}


// Before callback


$this->setState('failed');


// After callback


}


}
final class InventoryOperato
r

{

public function __invoke(TransitionEvent $transitionEvent): voi
d

{

$stateMachine = $transitionEvent->getStateMachine()
;

/** @var Payment $payment *
/

$payment = $stateMachine->getObject()
;

// Reduce inventory of bought product
s

}

}
$config =
[

// ..
.

'callbacks' =>
[

'before' =>
[

'reduce_amount' => [
'on' => ['pay']
,

'do' => new InventoryOperator()
,

]
,

]
,

]
,

];
On -> transition


From -> state


To -> state
Callbacks types
Symfony Work
fl
ow
$dispatcher = new EventDispatcher()
;

$dispatcher->addListener
(

'workflow.payment.enter.paid',
 

new PaymentPaidListener(
)

)
;

$workflow = new Workflow($definition, $marking, $dispatcher, 'payment');
final class PaymentPaidListener


{


public function __invoke(EnterEvent $event): void


{


// Reduce inventory of bought products


}


}
$dispatcher = new EventDispatcher()
;

$dispatcher->addListener
(

'workflow.payment.enter.paid',
 

new PaymentPaidListener(
)

);
$workflow = new Workflow($definition, $marking, $dispatcher, 'payment');
final class PaymentPaidListener


{


public function __invoke(EnterEvent $event): void


{


// Reduce inventory of bought products


}


}
$dispatcher = new EventDispatcher()
;

$dispatcher->addListener(
'workflow.payment.enter.paid',
 

new PaymentPaidListener(
)

)
;

$workflow = new Workflow($definition, $marking, $dispatcher, 'payment');
final class PaymentPaidListener


{


public function __invoke(EnterEvent $event): void


{


// Reduce inventory of bought products


}


}
$dispatcher = new EventDispatcher()
;

$dispatcher->addListener(
'workflow.payment.enter.paid',
new PaymentPaidListener(
)

)
;

$workflow = new Workflow($definition, $marking, $dispatcher, 'payment');
final class PaymentPaidListener


{


public function __invoke(EnterEvent $event): void


{


// Reduce inventory of bought products


}


}
$dispatcher = new EventDispatcher()
;

$dispatcher->addListener(
'workflow.payment.enter.paid',
 

new PaymentPaidListener(
)

)
;

$workflow = new Workflow($definition, $marking, $dispatcher, 'payment');
final class PaymentPaidListener


{


public function __invoke(EnterEvent $event): void


{


// Reduce inventory of bought products


}


}
work
fl
ow.[place type]


work
fl
ow.[work
fl
ow name].[place type]


work
fl
ow.[work
fl
ow name].[place type].[place name]
Actions
leave -> current place


enter -> which place(places) will be visited


entered -> which place(places) were visited
Types for places
work
fl
ow.[transition type]


work
fl
ow.[work
fl
ow name].[transition type]


work
fl
ow.[work
fl
ow name].[transition type].[transition name]
Actions
guard -> possibility to validate transition


transition -> which transition will be executed


completed -> which transition was executed


announce -> which transition are available now
Types for transitions
class Workflow implements WorkflowInterface


{


public function apply(/** */
)

{

$this->leave(/** */)
;

$this->transition(/** */);
$this->enter(/** */)
;

/** Making transition */
$this->markingStore->setMarking($payment, 'failed', $context)
;

$this->entered(/** */)
;

$this->completed(/** */)
;

$this->announce(/** */)
;

}

}
WinzouStateMachine
final class BlockAuthorizer


{


public function __invoke(): bool


{


return false;


}


}
$config =
[

/** ... *
/

'callbacks' =>
[

/** ... *
/

'guard' =>
[

'guard-blocked' =>
[

'to' => ['blocked']
,

'do' => new BlockedAuthorizer()
,

]
,

]
,

]
,

];
Symfony Work
fl
ow
final class BlockedGuardListener


{


public function __invoke(GuardEvent $event): void


{


$event->setBlocked(true);


}


}
$dispatcher->addListener
(

'workflow.payment.guard.block'
,

new BlockedGuardListener(
)

)
;
Th
e end of chapter 3
Summary
De
fi
ne possible states and relation between them


Protect business rules (with guards)


Trigger other services on transitions


Ease to add new possible transitions


Trigger other state changes as a reaction
WinzouStateMachine vs Symfony Work
fl
ow
Why should you care?
Common issues
Business logic wired up in
con
fi
guration
fi
les
Describe problem with state machine


but implement directly in code
Possibility to destroy state of entities


if state machine is omitted
😭
setState(…)
lchrusciel/RawStateMachine
@Sylius
Thank you!
@lukaszchrusciel

More Related Content

What's hot

November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2Kacper Gunia
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needKacper Gunia
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016Kacper Gunia
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesCiaranMcNulty
 
Introduction to DI(C)
Introduction to DI(C)Introduction to DI(C)
Introduction to DI(C)Radek Benkel
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Kacper Gunia
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixturesBill Chang
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Vladyslav Riabchenko
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Fabien Potencier
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
php 2 Function creating, calling, PHP built-in function
php 2 Function creating, calling,PHP built-in functionphp 2 Function creating, calling,PHP built-in function
php 2 Function creating, calling, PHP built-in functiontumetr1
 

What's hot (20)

The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 
Introduction to DI(C)
Introduction to DI(C)Introduction to DI(C)
Introduction to DI(C)
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
php 2 Function creating, calling, PHP built-in function
php 2 Function creating, calling,PHP built-in functionphp 2 Function creating, calling,PHP built-in function
php 2 Function creating, calling, PHP built-in function
 

Similar to Dutch php a short tale about state machine

A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machineŁukasz Chruściel
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2eugenio pombi
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machineŁukasz Chruściel
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application frameworkDustin Filippini
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにYuya Takeyama
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersKacper Gunia
 
Practical approach for testing your software with php unit
Practical approach for testing your software with php unitPractical approach for testing your software with php unit
Practical approach for testing your software with php unitMario Bittencourt
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDAleix Vergés
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Arnaud Langlade
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...DevClub_lv
 

Similar to Dutch php a short tale about state machine (20)

A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
WordPress as an application framework
WordPress as an application frameworkWordPress as an application framework
WordPress as an application framework
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Practical approach for testing your software with php unit
Practical approach for testing your software with php unitPractical approach for testing your software with php unit
Practical approach for testing your software with php unit
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 

More from Łukasz Chruściel

Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API ProjectsŁukasz Chruściel
 
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionŁukasz Chruściel
 
SyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfSyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfŁukasz Chruściel
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsŁukasz Chruściel
 
SymfonyLive Online 2023 - Is SOLID dead? .pdf
SymfonyLive Online 2023 - Is SOLID dead? .pdfSymfonyLive Online 2023 - Is SOLID dead? .pdf
SymfonyLive Online 2023 - Is SOLID dead? .pdfŁukasz Chruściel
 
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Łukasz Chruściel
 
4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdfŁukasz Chruściel
 
4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdfŁukasz Chruściel
 
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaBoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaŁukasz Chruściel
 
What we've learned designing new Sylius API
What we've learned designing new Sylius APIWhat we've learned designing new Sylius API
What we've learned designing new Sylius APIŁukasz Chruściel
 
How to optimize background processes.pdf
How to optimize background processes.pdfHow to optimize background processes.pdf
How to optimize background processes.pdfŁukasz Chruściel
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfŁukasz Chruściel
 
How to optimize background processes - when Sylius meets Blackfire
How to optimize background processes - when Sylius meets BlackfireHow to optimize background processes - when Sylius meets Blackfire
How to optimize background processes - when Sylius meets BlackfireŁukasz Chruściel
 
BDD in practice based on an open source project
BDD in practice based on an open source projectBDD in practice based on an open source project
BDD in practice based on an open source projectŁukasz Chruściel
 
Diversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectDiversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectŁukasz Chruściel
 

More from Łukasz Chruściel (17)

Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024  - Need for Speed: Removing speed bumps in API ProjectsConFoo 2024  - Need for Speed: Removing speed bumps in API Projects
ConFoo 2024 - Need for Speed: Removing speed bumps in API Projects
 
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solutionConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
ConFoo 2024 - Sylius 2.0, top-notch eCommerce for customizable solution
 
SyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdfSyliusCon - Typical pitfalls of Sylius development.pdf
SyliusCon - Typical pitfalls of Sylius development.pdf
 
Need for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API ProjectsNeed for Speed: Removing speed bumps in API Projects
Need for Speed: Removing speed bumps in API Projects
 
SymfonyLive Online 2023 - Is SOLID dead? .pdf
SymfonyLive Online 2023 - Is SOLID dead? .pdfSymfonyLive Online 2023 - Is SOLID dead? .pdf
SymfonyLive Online 2023 - Is SOLID dead? .pdf
 
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
Worldwide Software Architecture Summit'23 - BDD and why most of us do it wron...
 
4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf4Developers - Rozterki i decyzje.pdf
4Developers - Rozterki i decyzje.pdf
 
4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf4Developers - Sylius CRUD generation revisited.pdf
4Developers - Sylius CRUD generation revisited.pdf
 
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API SyliusaBoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
BoilingFrogs - Rozterki i decyzje. Czego się nauczyliśmy projektując API Syliusa
 
What we've learned designing new Sylius API
What we've learned designing new Sylius APIWhat we've learned designing new Sylius API
What we've learned designing new Sylius API
 
How to optimize background processes.pdf
How to optimize background processes.pdfHow to optimize background processes.pdf
How to optimize background processes.pdf
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdf
 
How to optimize background processes - when Sylius meets Blackfire
How to optimize background processes - when Sylius meets BlackfireHow to optimize background processes - when Sylius meets Blackfire
How to optimize background processes - when Sylius meets Blackfire
 
BDD in practice based on an open source project
BDD in practice based on an open source projectBDD in practice based on an open source project
BDD in practice based on an open source project
 
Diversified application testing based on a Sylius project
Diversified application testing based on a Sylius projectDiversified application testing based on a Sylius project
Diversified application testing based on a Sylius project
 
Why do I love and hate php?
Why do I love and hate php?Why do I love and hate php?
Why do I love and hate php?
 

Recently uploaded

KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 

Recently uploaded (20)

KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 

Dutch php a short tale about state machine

  • 1. A SHORT TALE ABOUT STATE MACHINE
  • 2. Once upon a time…
  • 4.
  • 5. final class Payment { private bool $pending = false; }
  • 6.
  • 7. Th e end of chapter 1
  • 8. A few days later
  • 9.
  • 10. final class Payment { private bool $pending = false; private bool $failed = false; }
  • 11.
  • 12. final class Payment { private bool $pending = false; private bool $failed = false; }
  • 13. final class Payment { public const NEW = 1; public const PENDING = 2; public const FAILED = 3; private int $state = self::NEW; } ?
  • 14.
  • 16. (Q, Σ, δ, q0, F) Q = a fi nite set of states Σ = a fi nite, nonempty input alphabet δ = a series of transition functions q0 = the starting state F = the set of accepting states
  • 18. Let’s do the research!
  • 19. De fi ne possible states and relation between them Protect business rules Integrate other services on transitions What do we expect?
  • 21. Callback’s execution in con fi g fi le Used heavily in Sylius Con fi gurable arguments of service Services have to be public in order to integrate them with state machine Without stable release, yet battle-tested and robust
  • 22.
  • 23.
  • 24. $config = [ 'graph' => 'payment' , 'property_path' => 'state' , 'states' => ['new','pending','failed','paid'] , 'transitions' => [ 'process' => [ 'from' => ['new'] , 'to' => 'pending' , ] , 'fail' => [ 'from' => ['pending'] , 'to' => 'failed' , ] , 'pay' => [ 'from' => ['pending'] , 'to' => 'paid' , ] , ] , ];
  • 25. $config = [ 'graph' => 'payment' , 'property_path' => 'state' , 'states' => ['new','pending','failed','paid'], 'transitions' => [ 'process' => [ 'from' => ['new'] , 'to' => 'pending' , ] , 'fail' => [ 'from' => ['pending'] , 'to' => 'failed' , ] , 'pay' => [ 'from' => ['pending'] , 'to' => 'paid' , ] , ] , ];
  • 26. $config = [ 'graph' => 'payment' , 'property_path' => 'state', 'states' => ['new','pending','failed','paid'] , 'transitions' => [ 'process' => [ 'from' => ['new'] , 'to' => 'pending' , ] , 'fail' => [ 'from' => ['pending'] , 'to' => 'failed' , ] , 'pay' => [ 'from' => ['pending'] , 'to' => 'paid' , ] , ] , ];
  • 27. $config = [ 'graph' => 'payment' , 'property_path' => 'state' , 'states' => ['new','pending','failed','paid'], 'transitions' => [ 'process' => [ 'from' => ['new'] , 'to' => 'pending' , ] , 'fail' => [ 'from' => ['pending'] , 'to' => 'failed' , ] , 'pay' => [ 'from' => ['pending'] , 'to' => 'paid' , ] , ] , ];
  • 29. Maintained by Symfony Flex support Work fl ow & state machine support Execution of external services with events XML / YAML / PHP support out-of-the-box Best documentation hands down
  • 30.
  • 31.
  • 32. $definitionBuilder = new DefinitionBuilder() ; $definition = $definitionBuilder->addPlaces(['new','pending','failed','paid'] ) ->addTransition(new Transition('process', 'new', 'pending') ) ->addTransition(new Transition('fail', [‘pending'], 'failed') ) ->addTransition(new Transition('pay', 'pending', 'paid') ) ->build( ) ; $singleState = true ; $property = 'state' ; $marking = new MethodMarkingStore($singleState, $property) ; $workflow = new Workflow($definition, $marking, null, 'payment');
  • 33. $definitionBuilder = new DefinitionBuilder() ; $definition = $definitionBuilder->addPlaces(['new','pending','failed','paid'] ) ->addTransition(new Transition('process', 'new', 'pending') ) ->addTransition(new Transition('fail', ['pending'], 'failed') ) ->addTransition(new Transition('pay', 'pending', 'paid') ) ->build( ) ; $singleState = true ; $property = 'state' ; $marking = new MethodMarkingStore($singleState, $property) ; $workflow = new Workflow($definition, $marking, null, 'payment');
  • 34. $definitionBuilder = new DefinitionBuilder() ; $definition = $definitionBuilder->addPlaces(['new','pending','failed','paid'] ) ->addTransition(new Transition('process', 'new', 'pending') ) ->addTransition(new Transition('fail', [‘pending'], 'failed') ) ->addTransition(new Transition('pay', 'pending', 'paid') ) ->build( ) ; $singleState = true ; $property = 'state' ; $marking = new MethodMarkingStore($singleState, $property) ; $workflow = new Workflow($definition, $marking, null, 'payment');
  • 36. Oldest and most popular implementation (in terms of stars) Least used implementation (in terms of daily installs according to packagist) Extendability with events & callbacks de fi nition Perhaps reached its EOL (https://github.com/yohang/Finite/issues/161) It is said to be little bit heavier implementation compared to Winzou
  • 37.
  • 38.
  • 40. final class Payment { public const NEW = 'new'; private string $state = self::NEW; public function getState(): string { return $this->state; } public function setState(string $state): void { $this->state = $state } }
  • 42. $payment = new Payment() ; $stateMachine = new StateMachine($payment, $config) ; $stateMachine->apply('process') ; $stateMachine->apply('fail');
  • 44. $payment = new Payment() ; $workflow->apply($payment, 'process') ; $workflow->apply($payment, 'fail');
  • 45.
  • 46.
  • 47. Th e end of chapter 2
  • 49.
  • 51. final class InventoryOperato r { public function __invoke(TransitionEvent $transitionEvent): voi d { $stateMachine = $transitionEvent->getStateMachine() ; /** @var Payment $payment * / $payment = $stateMachine->getObject() ; // Reduce inventory of bought product s } } $config = [ // .. . 'callbacks' => [ 'before' => [ 'reduce_amount' => [ 'on' => ['pay'] , 'do' => new InventoryOperator() , ] , ] , ] , ];
  • 52. final class InventoryOperato r { public function __invoke(TransitionEvent $transitionEvent): voi d { $stateMachine = $transitionEvent->getStateMachine() ; /** @var Payment $payment * / $payment = $stateMachine->getObject() ; // Reduce inventory of bought product s } } $config = [ // .. . 'callbacks' => [ 'before' => [ 'reduce_amount' => [ 'on' => ['pay'] , 'do' => new InventoryOperator() , ] , ] , ] , ];
  • 53. final class InventoryOperato r { public function __invoke(TransitionEvent $transitionEvent): voi d { $stateMachine = $transitionEvent->getStateMachine() ; /** @var Payment $payment * / $payment = $stateMachine->getObject() ; // Reduce inventory of bought product s } } $config = [ // .. . 'callbacks' => [ 'before' => [ 'reduce_amount' => [ 'on' => ['pay'] , 'do' => new InventoryOperator() , ] , ] , ] , ];
  • 54. Guard Before After Callbacks types * Same can be achieved with dispatched events
  • 55. class StateMachine implements StateMachineInterface { public function apply(/** */): void { // Guard callback if (!$this->can($transition)) { throw new SMException(); } // Before callback $this->setState('failed'); // After callback } }
  • 56. final class InventoryOperato r { public function __invoke(TransitionEvent $transitionEvent): voi d { $stateMachine = $transitionEvent->getStateMachine() ; /** @var Payment $payment * / $payment = $stateMachine->getObject() ; // Reduce inventory of bought product s } } $config = [ // .. . 'callbacks' => [ 'before' => [ 'reduce_amount' => [ 'on' => ['pay'] , 'do' => new InventoryOperator() , ] , ] , ] , ];
  • 57. On -> transition From -> state To -> state Callbacks types
  • 59. $dispatcher = new EventDispatcher() ; $dispatcher->addListener ( 'workflow.payment.enter.paid', new PaymentPaidListener( ) ) ; $workflow = new Workflow($definition, $marking, $dispatcher, 'payment'); final class PaymentPaidListener { public function __invoke(EnterEvent $event): void { // Reduce inventory of bought products } }
  • 60. $dispatcher = new EventDispatcher() ; $dispatcher->addListener ( 'workflow.payment.enter.paid', new PaymentPaidListener( ) ); $workflow = new Workflow($definition, $marking, $dispatcher, 'payment'); final class PaymentPaidListener { public function __invoke(EnterEvent $event): void { // Reduce inventory of bought products } }
  • 61. $dispatcher = new EventDispatcher() ; $dispatcher->addListener( 'workflow.payment.enter.paid', new PaymentPaidListener( ) ) ; $workflow = new Workflow($definition, $marking, $dispatcher, 'payment'); final class PaymentPaidListener { public function __invoke(EnterEvent $event): void { // Reduce inventory of bought products } }
  • 62. $dispatcher = new EventDispatcher() ; $dispatcher->addListener( 'workflow.payment.enter.paid', new PaymentPaidListener( ) ) ; $workflow = new Workflow($definition, $marking, $dispatcher, 'payment'); final class PaymentPaidListener { public function __invoke(EnterEvent $event): void { // Reduce inventory of bought products } }
  • 63. $dispatcher = new EventDispatcher() ; $dispatcher->addListener( 'workflow.payment.enter.paid', new PaymentPaidListener( ) ) ; $workflow = new Workflow($definition, $marking, $dispatcher, 'payment'); final class PaymentPaidListener { public function __invoke(EnterEvent $event): void { // Reduce inventory of bought products } }
  • 64. work fl ow.[place type] work fl ow.[work fl ow name].[place type] work fl ow.[work fl ow name].[place type].[place name] Actions
  • 65. leave -> current place enter -> which place(places) will be visited entered -> which place(places) were visited Types for places
  • 66. work fl ow.[transition type] work fl ow.[work fl ow name].[transition type] work fl ow.[work fl ow name].[transition type].[transition name] Actions
  • 67. guard -> possibility to validate transition transition -> which transition will be executed completed -> which transition was executed announce -> which transition are available now Types for transitions
  • 68. class Workflow implements WorkflowInterface { public function apply(/** */ ) { $this->leave(/** */) ; $this->transition(/** */); $this->enter(/** */) ; /** Making transition */ $this->markingStore->setMarking($payment, 'failed', $context) ; $this->entered(/** */) ; $this->completed(/** */) ; $this->announce(/** */) ; } }
  • 69.
  • 70.
  • 72. final class BlockAuthorizer { public function __invoke(): bool { return false; } } $config = [ /** ... * / 'callbacks' => [ /** ... * / 'guard' => [ 'guard-blocked' => [ 'to' => ['blocked'] , 'do' => new BlockedAuthorizer() , ] , ] , ] , ];
  • 74. final class BlockedGuardListener { public function __invoke(GuardEvent $event): void { $event->setBlocked(true); } } $dispatcher->addListener ( 'workflow.payment.guard.block' , new BlockedGuardListener( ) ) ;
  • 75.
  • 76. Th e end of chapter 3
  • 78. De fi ne possible states and relation between them Protect business rules (with guards) Trigger other services on transitions Ease to add new possible transitions Trigger other state changes as a reaction
  • 80.
  • 81. Why should you care?
  • 83. Business logic wired up in con fi guration fi les
  • 84. Describe problem with state machine but implement directly in code
  • 85. Possibility to destroy state of entities if state machine is omitted
  • 86.
  • 87. 😭