सिम्फनी - उन्नत अवधारणाओं
इस अध्याय में, हम सिम्फनी ढांचे में कुछ उन्नत अवधारणाओं के बारे में जानेंगे।
HTTP कैश
एक वेब अनुप्रयोग में कैशिंग प्रदर्शन में सुधार करता है। उदाहरण के लिए, एक शॉपिंग कार्ट वेब एप्लिकेशन में गर्म उत्पादों को सीमित समय के लिए कैश किया जा सकता है, ताकि इसे डेटाबेस को हिट किए बिना ग्राहक को त्वरित रूप से प्रस्तुत किया जा सके। निम्नलिखित कैश के कुछ बुनियादी घटक हैं।
कैश आइटम
कैश आइटम कुंजी / मूल्य जोड़ी के रूप में संग्रहीत जानकारी की एक एकल इकाई है। key तार और होना चाहिए valueकोई भी PHP ऑब्जेक्ट हो सकता है। PHP वस्तुओं को क्रमांकन द्वारा स्ट्रिंग के रूप में संग्रहीत किया जाता है और वस्तुओं को पढ़ते समय वापस वस्तुओं में परिवर्तित किया जाता है।
कैश एडेप्टर
कैश एडेप्टर एक स्टोर में आइटम को स्टोर करने के लिए वास्तविक तंत्र है। स्टोर एक मेमोरी, फाइल सिस्टम, डेटाबेस, रेडिस आदि हो सकता है। कैश घटक एक प्रदान करता हैAdapterInterfaceजिसके माध्यम से एक एडाप्टर कैश आइटम को बैक-एंड स्टोर में स्टोर कर सकता है। बहुत सारे अंतर्निहित कैश एडेप्टर उपलब्ध हैं। उनमें से कुछ इस प्रकार हैं -
Array Cache एडेप्टर - Cache आइटम PHP array में स्टोर होते हैं।
फाइलसिस्टम कैश एडेप्टर - कैश आइटम्स को फाइलों में स्टोर किया जाता है।
PHP फ़ाइलें कैश एडाप्टर - कैश आइटम php फ़ाइलों के रूप में संग्रहीत हैं।
APCu कैश एडेप्टर - कैश आइटम PHP APCu विलोपन का उपयोग करके साझा मेमोरी में संग्रहीत किए जाते हैं।
रेडिस कैश एडेप्टर - कैश आइटम रेडिस सर्वर में संग्रहीत किए जाते हैं।
पीडीओ और डॉक्ट्रिन डीबीएएल कैश एडेप्टर - कैश आइटम डेटाबेस में संग्रहीत किए जाते हैं।
चेन कैश एडेप्टर - प्रतिकृति उद्देश्य के लिए कई कैश एडेप्टर को जोड़ती है।
प्रॉक्सी कैश एडेप्टर - कैश आइटम को थर्ड पार्टी अडैप्टर का उपयोग करके स्टोर किया जाता है, जो कैशेइमपूलइंटरफेस को लागू करता है।
कैश पूल
कैश पूल कैश आइटम का एक तार्किक भंडार है। कैश पूल को कैश एडेप्टर द्वारा कार्यान्वित किया जाता है।
सरल अनुप्रयोग
कैश अवधारणा को समझने के लिए एक सरल एप्लिकेशन बनाएं।
Step 1 - एक नया एप्लिकेशन बनाएं, cache-example।
cd /path/to/app
mkdir cache-example
cd cache-example
Step 2 - कैश कंपोनेंट इंस्टॉल करें।
composer require symfony/cache
Step 3 - एक फाइल सिस्टम एडेप्टर बनाएं।
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
$cache = new FilesystemAdapter();
Step 4 - कैश आइटम का उपयोग करके बनाएं getItem तथा setएडॉप्टर की विधि। getItem अपनी कुंजी का उपयोग करके कैश आइटम प्राप्त करता है। यदि कुंजी स्थायी नहीं है, तो यह एक नया आइटम बनाता है। सेट विधि वास्तविक डेटा संग्रहीत करता है।
$usercache = $cache->getitem('item.users');
$usercache->set(['jon', 'peter']);
$cache->save($usercache);
Step 5 - कैश आइटम का उपयोग करके प्रवेश करें getItem, isHit तथा getतरीका। isHit कैश आइटम की उपलब्धता की सूचना देता है और विधि वास्तविक डेटा प्रदान करता है।
$userCache = $cache->getItem('item.users');
if(!$userCache->isHit()) {
echo "item.users is not available";
} else {
$users = $userCache->get();
var_dump($users);
}
Step 6 - कैश आइटम का उपयोग करके हटाएं deleteItem तरीका।
$cache->deleteItem('item.users');
पूरी कोड सूची इस प्रकार है।
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
$cache = new FilesystemAdapter();
$usercache = $cache->getitem('item.users');
$usercache->set(['jon', 'peter']);
$cache->save($usercache);
$userCache = $cache->getItem('item.users');
if(!$userCache->isHit()) {
echo "item.users is not available";
} else {
$users = $userCache->get();
var_dump($users);
}
$cache->deleteItem('item.users');
?>
परिणाम
array(2) {
[0]=>
string(3) "jon"
[1]=>
string(5) "peter"
}
डिबग
डिबगिंग किसी एप्लिकेशन को विकसित करते समय सबसे लगातार गतिविधि में से एक है। सिम्फनी डिबगिंग की प्रक्रिया को आसान बनाने के लिए एक अलग घटक प्रदान करती है। हम सिम्फनी डीबगिंग टूल को केवल कॉल करके सक्षम कर सकते हैंenable डिबग क्लास की विधि।
use Symfony\Component\Debug\Debug
Debug::enable()
सिम्फनी दो कक्षाएं प्रदान करती है, ErrorHandler तथा ExceptionHandlerडिबगिंग उद्देश्य के लिए। जबकि ErrorHandler PHP त्रुटियों को पकड़ता है और उन्हें अपवादों में परिवर्तित करता है, ErrorException या FatalErrorException, ExceptionHandler बिना किसी अपवाद के PHP अपवादों को पकड़ता है और उन्हें उपयोगी PHP प्रतिक्रिया में परिवर्तित करता है। ErrorHandler और ExceptionHandler डिफ़ॉल्ट रूप से अक्षम हैं। हम रजिस्टर विधि का उपयोग करके इसे सक्षम कर सकते हैं।
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
ErrorHandler::register();
ExceptionHandler::register();
एक सिम्फनी वेब अनुप्रयोग में, debug environmentDebugBundle द्वारा प्रदान किया गया है। बंडल को एपकर्नेल में पंजीकृत करेंregisterBundles इसे सक्षम करने की विधि।
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
}
प्रोफाइलर
एक अनुप्रयोग के विकास के लिए एक विश्व स्तरीय रूपरेखा उपकरण की आवश्यकता होती है। प्रोफाइलिंग टूल किसी एप्लिकेशन के बारे में सभी रन-टाइम जानकारी इकट्ठा करता है जैसे कि निष्पादन समय, व्यक्तिगत मॉड्यूल का निष्पादन समय, डेटाबेस गतिविधि द्वारा लिया गया समय, मेमोरी उपयोग, आदि। एक वेब एप्लिकेशन को अनुरोध के समय जैसी बहुत अधिक जानकारी की आवश्यकता होती है, आदि। उपरोक्त मैट्रिक्स के अलावा एक प्रतिक्रिया, आदि बनाने के लिए समय लिया गया है।
सिम्फनी डिफ़ॉल्ट रूप से वेब एप्लिकेशन में ऐसी सभी सूचनाओं को सक्षम करता है। सिम्फनी नामक वेब प्रोफाइलिंग के लिए एक अलग बंडल प्रदान करता हैWebProfilerBundle। वेब प्रोफाइलर बंडल को वेब एप्लिकेशन में बंडल को एपकर्नेल के रजिस्टरबंडल्स विधि में पंजीकृत करके सक्षम किया जा सकता है।
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
}
वेब प्रोफ़ाइल घटक के तहत कॉन्फ़िगर किया जा सकता है web_profile section एप्लिकेशन कॉन्फ़िगरेशन फ़ाइल का, app/config/config.xml
web_profiler:
toolbar: false
position: bottom
सिम्फनी एप्लिकेशन पृष्ठ के निचले भाग में एक अलग अनुभाग के रूप में प्रोफाइल किए गए डेटा को दिखाता है।
सिम्फनी प्रोफाइल डेटा का उपयोग करके पेज के बारे में कस्टम विवरण जोड़ने का एक आसान तरीका भी प्रदान करता है DataCollectorInterface interfaceऔर टहनी टेम्पलेट। संक्षेप में, सिम्फनी एक वेब डेवलपर को सापेक्ष आसानी से एक शानदार रूपरेखा प्रदान करके एक विश्व स्तरीय अनुप्रयोग बनाने में सक्षम बनाता है।
सुरक्षा
जैसा कि पहले चर्चा की गई है, सिम्फनी अपने सुरक्षा घटक के माध्यम से एक मजबूत सुरक्षा ढांचा प्रदान करता है। सुरक्षा घटक को चार उप-घटकों में विभाजित किया गया है।
- सिम्फनी / सुरक्षा-कोर - कोर सुरक्षा कार्यक्षमता।
- सिम्फ़नी / सुरक्षा-http - HTTP प्रोटोकॉल में एकीकृत सुरक्षा सुविधा।
- symfony / security-csrf - वेब एप्लिकेशन में क्रॉस-साइट अनुरोध जालसाजी के खिलाफ सुरक्षा।
- सिम्फनी / सुरक्षा-एसएल - उन्नत अभिगम नियंत्रण सूची आधारित सुरक्षा ढांचा।
सरल प्रमाणीकरण और प्राधिकरण
आइए हम एक सरल डेमो एप्लिकेशन का उपयोग करके प्रमाणीकरण और प्राधिकरण की अवधारणा को जानें।
Step 1 - एक नया वेब एप्लिकेशन बनाएं securitydemo निम्नलिखित कमांड का उपयोग करना।
symfony new securitydemo
Step 2- सुरक्षा कॉन्फ़िगरेशन फ़ाइल का उपयोग करके एप्लिकेशन में सुरक्षा सुविधा सक्षम करें। सुरक्षा संबंधित कॉन्फ़िगरेशन को एक अलग फ़ाइल में रखा गया है,security.yml। डिफ़ॉल्ट कॉन्फ़िगरेशन निम्नानुसार है।
security:
providers:
in_memory:
memory: ~
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
#http_basic: ~
#form_login: ~
डिफ़ॉल्ट कॉन्फ़िगरेशन स्मृति-आधारित सुरक्षा प्रदाता और सभी पृष्ठों तक अनाम पहुंच को सक्षम करता है। फ़ायरवॉल अनुभाग पैटर्न से मेल खाती फ़ाइलों को बाहर करता है,^/(_(profiler|wdt)|css|images|js)/सुरक्षा ढांचे से। डिफ़ॉल्ट पैटर्न में स्टाइलशीट, चित्र, और जावा स्क्रिप्ट (प्लस प्रोफाइलर जैसे प्रोफाइलर) शामिल हैं।
Step 3 - HTTP आधारित सुरक्षा प्रमाणीकरण प्रणाली को मुख्य भाग में http_basic विकल्प जोड़कर सक्षम करें।
security:
# ...
firewalls:
# ...
main:
anonymous: ~
http_basic: ~
#form_login: ~
Step 4- मेमोरी प्रोवाइडर सेक्शन में कुछ यूजर्स जोड़ें। इसके अलावा, उपयोगकर्ताओं के लिए भूमिकाएँ जोड़ें।
security:
providers:
in_memory:
memory:
users:
myuser:
password: user
roles: 'ROLE_USER'
myadmin:
password: admin
roles: 'ROLE_ADMIN'
हमने दो उपयोगकर्ताओं को जोड़ा है, रोल रोल_यूएसईआर में उपयोगकर्ता और रोल रोलएडिन में व्यवस्थापक ।
Step 5- वर्तमान लॉग-इन उपयोगकर्ता का पूरा विवरण प्राप्त करने के लिए एनकोडर जोड़ें। एनकोडर का उद्देश्य वेब अनुरोध से वर्तमान उपयोगकर्ता ऑब्जेक्ट का पूरा विवरण प्राप्त करना है।
security:
# ...
encoders:
Symfony\Component\Security\Core\User\User: bcrypt
# ...
सिम्फनी एक इंटरफ़ेस प्रदान करता है, UserInterface उपयोगकर्ता विवरण, जैसे उपयोगकर्ता नाम, भूमिका, पासवर्ड आदि प्राप्त करने के लिए, हमें अपनी आवश्यकता के अनुसार इंटरफ़ेस को लागू करना होगा और इसे एनकोडर अनुभाग में कॉन्फ़िगर करना होगा।
उदाहरण के लिए, आइए विचार करें कि उपयोगकर्ता विवरण डेटाबेस में हैं। फिर, हमें उपयोगकर्ता से डेटाबेस का विवरण प्राप्त करने के लिए एक नया उपयोगकर्ता वर्ग बनाने और UserInterface विधियों को लागू करने की आवश्यकता है। एक बार डेटा उपलब्ध होने के बाद, उपयोगकर्ता को अनुमति देने / अस्वीकार करने के लिए सुरक्षा प्रणाली इसका उपयोग करती है। सिम्फनी मेमोरी प्रदाता के लिए एक डिफ़ॉल्ट उपयोगकर्ता कार्यान्वयन प्रदान करता है। एल्गोरिदम का उपयोग उपयोगकर्ता पासवर्ड को डिक्रिप्ट करने के लिए किया जाता है।
Step 6 - उपयोग करते हुए उपयोगकर्ता पासवर्ड एन्क्रिप्ट करें bcryptएल्गोरिथ्म और कॉन्फ़िगरेशन फ़ाइल में रखें। चूंकि हमने इस्तेमाल कियाbcryptएल्गोरिथ्म, उपयोगकर्ता ऑब्जेक्ट कॉन्फ़िगरेशन फ़ाइल में निर्दिष्ट पासवर्ड को डिक्रिप्ट करने की कोशिश करता है और फिर उपयोगकर्ता द्वारा दर्ज किए गए पासवर्ड से मिलान करने का प्रयास करता है। सिम्फनी कंसोल एप्लिकेशन पासवर्ड को एन्क्रिप्ट करने के लिए एक सरल कमांड प्रदान करता है।
php bin/console security:encode-password admin
Symfony Password Encoder Utility
================================
------------------ -----------------------------------
Key Value
------------------ ------------------------------------
Encoder used Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder
Encoded password
$2y$12$0Hy6/.MNxWdFcCRDdstHU.hT5j3Mg1tqBunMLIUYkz6..IucpaPNO
------------------ ------------------------------------
! [NOTE] Bcrypt encoder used: the encoder generated its own built-in salt.
[OK] Password encoding succeeded
Step 7 - एन्क्रिप्टेड पासवर्ड जेनरेट करने के लिए कमांड का उपयोग करें और इसे कॉन्फ़िगरेशन फाइल में अपडेट करें।
# To get started with security, check out the documentation:
# http://symfony.com/doc/current/security.html
security:
# http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
in_memory:
memory:
users:
user:
password: $2y$13$WsGWNufreEnVK1InBXL2cO/U7WftvfNvH
Vb/IJBH6JiYoDwVN4zoi
roles: 'ROLE_USER'
admin:
password: $2y$13$jQNdIeoNV1BKVbpnBuhKRuOL01NeMK
F7nEqEi/Mqlzgts0njK3toy
roles: 'ROLE_ADMIN'
encoders:
Symfony\Component\Security\Core\User\User: bcrypt
firewalls:
# disables authentication for assets and the profiler,
# adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
# activate different ways to authenticate
# http://symfony.com/doc/current/security.html#a-co
nfiguring-howyour-users-will-authenticate
http_basic: ~
# http://symfony.com/doc/current/cookbook/security/
form_login_setup.html
#form_login: ~
Step 8- अब, आवेदन के कुछ अनुभाग के लिए सुरक्षा लागू करें। उदाहरण के लिए, व्यवस्थापक अनुभाग को रोल-रोल में उपयोगकर्ताओं को प्रतिबंधित करें।
security:
# ...
firewalls:
# ...
default:
# ...
access_control:
# require ROLE_ADMIN for /admin*
- { path: ^/admin, roles: 'ROLE_ADMIN' }
Step 9 - DefaultController में निम्नानुसार एक व्यवस्थापक पृष्ठ जोड़ें।
/**
* @Route("/admin")
*/
public function adminLandingAction() {
return new Response('<html><body>This is admin section.</body></html>');
}
Step 10- अंत में, ब्राउज़र में सुरक्षा कॉन्फ़िगरेशन की जांच करने के लिए व्यवस्थापक पृष्ठ पर पहुंचें। ब्राउज़र उपयोगकर्ता नाम और पासवर्ड के लिए पूछेगा और केवल कॉन्फ़िगर किए गए उपयोगकर्ताओं को अनुमति देगा।
परिणाम
कार्यप्रवाह
वर्कफ़्लो एक उन्नत अवधारणा है जिसमें कई उद्यम अनुप्रयोगों का उपयोग होता है। ई-कॉमर्स एप्लिकेशन में, उत्पाद वितरण प्रक्रिया एक वर्कफ़्लो है। उत्पाद को पहले बिल (ऑर्डर निर्माण), स्टोर से खरीदा गया और पैक किया गया (पैकेजिंग / भेजने के लिए तैयार), और उपयोगकर्ता को भेजा गया। यदि कोई समस्या है, तो उत्पाद उपयोगकर्ता से वापस आ जाता है और ऑर्डर वापस कर दिया जाता है। कार्रवाई के प्रवाह का आदेश बहुत महत्वपूर्ण है। उदाहरण के लिए, हम बिलिंग के बिना कोई उत्पाद नहीं दे सकते।
सिम्फनी घटक एक वर्कफ़्लो को परिभाषित करने और प्रबंधित करने के लिए एक वस्तु-उन्मुख तरीका प्रदान करता है। एक प्रक्रिया में प्रत्येक चरण को कहा जाता हैplace और एक स्थान से दूसरे स्थान पर जाने के लिए आवश्यक क्रिया कहलाती है transition। वर्कफ़्लो बनाने के लिए स्थानों और संक्रमण के संग्रह को कहा जाता हैWorkflow definition।
हमें छुट्टी प्रबंधन के लिए एक सरल आवेदन बनाकर वर्कफ़्लो की अवधारणा को समझने दें।
Step 1 - एक नया एप्लिकेशन बनाएं, workflow-example।
cd /path/to/dev
mkdir workflow-example
cd workflow-example
composer require symfony/workflow
Step 2 - एक नया वर्ग बनाएं, Leave बीत रहा है applied_by, leave_on तथा status जिम्मेदार बताते हैं।
class Leave {
public $applied_by;
public $leave_on;
public $status;
}
यहां, apply_by उन कर्मचारियों को संदर्भित करता है जो छुट्टी चाहते हैं। छुट्टी_ पर छुट्टी की तारीख को संदर्भित करता है। स्थिति छुट्टी की स्थिति को संदर्भित करती है।
Step 3 - अवकाश प्रबंधन में चार स्थान हैं, लागू, in_process और स्वीकृत / अस्वीकृत।
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow;
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
$builder = new DefinitionBuilder();
$builder->addPlaces(['applied', 'in_process', 'approved', 'rejected']);
यहां, हमने एक नई परिभाषा का उपयोग किया है DefinitionBuilder और स्थानों का उपयोग करके जोड़ा गया addPlaces तरीका।
Step 4 - एक स्थान से दूसरे स्थान पर जाने के लिए आवश्यक क्रियाओं को परिभाषित करें।
$builder->addTransition(new Transition('to_process', 'applied', 'in_process'));
$builder->addTransition(new Transition('approve', 'in_process', 'approved'));
$builder->addTransition(new Transition('reject', 'in_process', 'rejected'));
यहाँ, हमारे पास तीन बदलाव हैं, to_process, approve तथा reject। to_process संक्रमण छुट्टी आवेदन स्वीकार करता है और लागू in_process से जगह को स्थानांतरित करता है। स्वीकृत परिवर्तन छुट्टी के आवेदन को मंजूरी देता है और अनुमोदित करने के लिए जगह को स्थानांतरित करता है। इसी तरह, संक्रमण को अस्वीकार करें छुट्टी के आवेदन को अस्वीकार कर देता है और अस्वीकार किए गए स्थान को स्थानांतरित करता है। हमने AddTransition विधि का उपयोग करके सभी संक्रमण बनाए हैं।
Step 5 - बिल्ड मेथड का उपयोग करके परिभाषा बनाएं।
$definition = $builder->build();
Step 6 - वैकल्पिक रूप से, परिभाषा को ग्राफविज़ डॉट प्रारूप के रूप में डंप किया जा सकता है, जिसे संदर्भ उद्देश्य के लिए छवि फ़ाइल में परिवर्तित किया जा सकता है।
$dumper = new GraphvizDumper();
echo $dumper->dump($definition);
Step 7 - एक मार्किंग स्टोर बनाएं, जिसका उपयोग ऑब्जेक्ट के वर्तमान स्थानों / स्थिति को संग्रहीत करने के लिए किया जाता है।
$marking = new SingleStateMarkingStore('status');
यहां, हमने उपयोग किया है SingleStateMarkingStoreवर्ग चिह्न बनाने के लिए और यह वस्तु की स्थिति संपत्ति में वर्तमान स्थिति को चिह्नित करता है। हमारे उदाहरण में, ऑब्जेक्ट लीव ऑब्जेक्ट है।
Step 8 - परिभाषा और अंकन का उपयोग करके वर्कफ़्लो बनाएं।
$leaveWorkflow = new Workflow($definition, $marking);
यहां, हमने उपयोग किया है Workflow वर्कफ़्लो बनाने के लिए क्लास।
Step 9 - वर्कफ़्लो फ्रेमवर्क की रजिस्ट्री में वर्कफ़्लो को जोड़ें Registry कक्षा।
$registry = new Registry();
$registry->add($leaveWorkflow, Leave::class);
Step 10 - अंत में, किसी दिए गए संक्रमण का उपयोग करके लागू किया गया है या नहीं यह जानने के लिए वर्कफ़्लो का उपयोग करें can विधि और यदि हां, तो applyलागू पद्धति का उपयोग करके संक्रमण। जब एक संक्रमण लागू होता है, तो वस्तु की स्थिति एक स्थान से दूसरे स्थान पर जाती है।
$workflow = $registry->get($leave);
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo "Can we approve the start process now? " . $workflow->can($leave, 'to_process') . "\r\n";
$workflow->apply($leave, 'to_process');
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo $leave->status . "\r\n";
$workflow->apply($leave, 'approve');
echo $leave->status . "\r\n";
पूरा कोडिंग इस प्रकार है -
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Workflow\DefinitionBuilder;
use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow;
use Symfony\Component\Workflow\MarkingStore\SingleStateMarkingStore;
use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\Dumper\GraphvizDumper;
class Leave {
public $applied_by;
public $leave_on;
public $status;
}
$builder = new DefinitionBuilder();
$builder->addPlaces(['applied', 'in_process', 'approved', 'rejected']);
$builder->addTransition(new Transition('to_process', 'applied', 'in_process'));
$builder->addTransition(new Transition('approve', 'in_process', 'approved'));
$builder->addTransition(new Transition('reject', 'in_process', 'rejected'));
$definition = $builder->build();
// $dumper = new GraphvizDumper();
// echo $dumper->dump($definition);
$marking = new SingleStateMarkingStore('status');
$leaveWorkflow = new Workflow($definition, $marking);
$registry = new Registry();
$registry->add($leaveWorkflow, Leave::class);
$leave = new Leave();
$leave->applied_by = "Jon";
$leave->leave_on = "1998-12-12";
$leave->status = 'applied';
$workflow = $registry->get($leave);
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo "Can we approve the start process now? " . $workflow->can($leave, 'to_process') . "\r\n";
$workflow->apply($leave, 'to_process');
echo "Can we approve the leave now? " . $workflow->can($leave, 'approve') . "\r\n";
echo $leave->status . "\r\n";
$workflow->apply($leave, 'approve');
echo $leave->status . "\r\n";
?>
परिणाम
Can we approve the leave now?
Can we approve the start process now? 1
Can we approve the leave now? 1
in_process
approved