تنفيذ آلات الدولة على Zend Framework3 + Doctine2

مقدمة: لماذا نحتاج إلى جهاز الدولة


في التطبيقات ، غالبًا ما يكون من الضروري تقييد الوصول إلى إجراءات معينة على كائن. لهذا ، يتم استخدام وحدات RBAC التي تحل مشكلة تقييد الوصول اعتمادًا على حقوق المستخدم. تظل مهمة إدارة الإجراءات ، وفقًا لحالة الكائن ، بدون حل. يتم حل هذه المشكلة جيدًا باستخدام جهاز حالة أو جهاز حالة. لا تسمح لك آلة الحالة الملائمة بجمع جميع قواعد الانتقالات بين حالات الكائن في مكان واحد فحسب ، بل تضع أيضًا بعض الترتيب في التعليمات البرمجية عن طريق فصل قواعد الانتقالات والتحقق من الشروط والتعامل معها وإخضاعها للقواعد العامة.


أرغب في مشاركة تنفيذ جهاز الحالة لـ Zend Framework 3 باستخدام Doctrine 2
للعمل مع قاعدة البيانات. يمكن العثور على المشروع نفسه هنا .


وهنا أريد أن أشارك المبادئ الأساسية المنصوص عليها.


دعنا نبدأ




سنقوم بتخزين وصف الرسم البياني الانتقالي في جدول قاعدة البيانات للأسباب التالية:


  1. هذا واضح.
  2. يسمح لك باستخدام قاموس الحالة نفسه المستخدم في قاموس الاهتمام
    لنا كائن له دولة.
  3. يسمح لك بضمان سلامة قاعدة البيانات باستخدام المفاتيح الخارجية.

إن استخدام آلة حالة محدودة غير حتمية سيزيد من مرونة حلنا.


سيتم وصف الرسم البياني الانتقالي باستخدام زوج من الجدولين A و B ، مرتبطان بعلاقة واحد لكثير.


الجدول أ:


CREATE TABLE `tr_a` ( `id` int(11) NOT NULL AUTO_INCREMENT, `src_id` varchar(32) COLLATE utf8_unicode_ci NOT NULL, `action_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL COMMENT ' ', `condition` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '   ', PRIMARY KEY (`id`), KEY `IDX_96B84B3BFF529AC` (`src_id`), KEY `IDX_96B84B3B9D32F035` (`action_id`), CONSTRAINT `FK_96B84B3B9D32F035` FOREIGN KEY (`action_id`) REFERENCES `action` (`id`), CONSTRAINT `FK_96B84B3BFF529AC` FOREIGN KEY (`src_id`) REFERENCES `state` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

الجدول ب:


 CREATE TABLE `tr_b` ( `id` int(11) NOT NULL AUTO_INCREMENT, `transition_a_id` int(11) NOT NULL, `dst_id` varchar(32) COLLATE utf8_unicode_ci NOT NULL, `weight` int(11) DEFAULT NULL COMMENT '  ,- , null-  ', `condition` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '   ', `pre_functor` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ' ,  ,   ', `post_functor` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ' ,  ,   ', PRIMARY KEY (`id`), KEY `IDX_E12699CB85F4C374` (`transition_a_id`), KEY `IDX_E12699CBE1885D19` (`dst_id`), CONSTRAINT `FK_E12699CB85F4C374` FOREIGN KEY (`transition_a_id`) REFERENCES `tr_a` (`id`), CONSTRAINT `FK_E12699CBE1885D19` FOREIGN KEY (`dst_id`) REFERENCES `state` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

سأحذف تعريف فئات الكيانات ؛ يمكنك رؤية مثال هنا:


  1. الجدول أ
  2. الجدول ب

كل شيء قياسي هنا ، بما في ذلك وصف للعلاقة بين الكيانات.


لاستخدام آلة الدولة ، نحتاج فقط إلى بعض الأساليب العامة


 /** *            * @param object $objE * @param string $action * @param array $data extra data * @return array * @throws ExceptionNS\StateMachineException */ public function doAction($objE, $action, array $data = []) /** *          * @param object $objE * @param string $action * @param array $data * @return bool */ public function hasAction($objE, $action, $data=[]) 

هناك العديد من الطرق العامة للاستخدام المريح ، ولكن هنا أود الانتباه إلى خوارزمية طريقة doAction() الرئيسية.


من الكائن نحصل على حالته.


بمعرفته ومعرف الإجراء ، يمكن العثور على الكيان- A بسهولة في جدول الانتقال A.
يسمح لك الشرط الذي تم الحصول عليه بواسطة معرف الشرط ، والذي يقع في condition من الكيان- A ، بالتحقق مما إذا كان يمكن تنفيذ الإجراء. على وجه الخصوص ، يمكن استخدام بند RBAC المذكور في البداية في مدقق الشرط.


سيتم العثور على المدقق من خلال المعرف من حقل condition خلال ValidatorPluginManager و
يجب تنفيذ \Zend\Validator\ValidatorInterface . أفضل استخدام الورثة من ValidatorChain . وهذا يجعل من السهل تغيير تكوين الظروف الخاضعة للرقابة وإعادة استخدام أدوات التحقق البسيطة كجزء من سلاسل الاختبار.


حددنا الانتقال ، والتحقق من الحالة. لأن لدينا غير حتمية
آلة الدولة ، قد تكون نتيجة الإجراء واحدة من عدة ولايات.


مثل هذه الحالات ليست شائعة جدًا ، لكن المشروع المقترح سهل التنفيذ.
من خلال الاتصال A - <B ، نحصل على مجموعة من الحالات الجديدة المحتملة للكائن (الكيان B).
لتحديد حالة واحدة ، نتحقق من شروط الكيان B من المجموعة الناتجة ، ونفرزها حسب weight من الأكبر إلى الأصغر في مجال weight . يمنحنا أول فحص ناجح للحالة Entity-B ، حيث توجد حالة جديدة للكائن (انظر الحقل dst_id ).


يتم تحديد الدولة الجديدة. الآن ، قبل تغيير الحالة ، سيتم تنفيذ آلة الحالة
الإجراءات المحددة في البادئة ، ثم ستغير الحالة وتنفيذ الإجراءات ،
المعرفة في الوظيفة اللاحقة. سيحصل جهاز الحالة على ممولين بناءً على الاسم من حقل pre_functor للعملية البادئة و post_functor لوظيفة post باستخدام مدير البرنامج الإضافي وسيستدعي طريقة __invoke () للكائنات المستلمة.


ليس من الضروري تغيير الحالة باستخدام المواهب. هذه هي مهمة آلة الدولة. إذا لم تكن هناك حاجة لتنفيذ إجراءات إضافية عند تغيير الحالة ، فقم بتعيين قيمة فارغة على الحقول المذكورة أعلاه.


رقائق أخرى:


  1. في مجالات condition الجداول الانتقالية ، pre_funtor ، post_functor أستخدم الأسماء المستعارة ، في رأيي أنها مريحة.
  2. لتوفير الراحة البصرية ، قم بإنشاء طريقة عرض من الجدولين A و B.
  3. أستخدم معرفات السلسلة كمفتاح أساسي في قواميس الحالة والعمل. هذا ليس ضروريًا ، ولكنه مريح. يمكن أيضًا استخدام قواميس ذات معرفات رقمية.
  4. نظرًا لاستخدام آلة حالة محدودة غير محددة ، لا يجب أن يؤدي الإجراء إلى تغيير في الحالة. هذا يسمح لك بوصف إجراءات مثل العرض ، على سبيل المثال.
  5. بالإضافة إلى طرق التحقق من إجراء وتنفيذ إجراء ، هناك عدد من الطرق العامة التي تسمح ، على سبيل المثال ، بالحصول على قائمة الإجراءات لحالة معينة من الكائن أو قائمة الإجراءات المتاحة لحالة معينة من الكائن ، مع مراعاة عمليات التحقق. غالبًا في الواجهة في الشبكات لكل سجل ، تحتاج إلى إظهار مجموعة من الإجراءات. ستساعد هذه الأساليب من آلات الحالة في الحصول على القائمة الضرورية.
  6. بالطبع ، يمكن استدعاء آلات الحالة الأخرى داخل الجنازير ، علاوة على ذلك ، يمكنك الاتصال بنفسك ، ولكن باستخدام كائن مختلف أو بنفس الكائن ، ولكن بعد تغيير الحالة (أي في حالة ما بعد الجنازير). هذا مفيد في بعض الأحيان لتنظيم التحولات المتتالية في ظل الظروف "المفاجئة" المتغيرة من العميل ؛)

الخلاصة


على الرغم من المهام العديدة المناسبة بشكل مثالي لاستخدام أجهزة الحالة ، إلا أن مبرمجي الويب يستخدمونها نادرًا نسبيًا. القرارات نفسها التي رأيتها بدت لي وحشية.


آمل أن يساعد الحل المقترح شخصًا على توفير الوقت في التنفيذ.

Source: https://habr.com/ru/post/ar413701/


All Articles