الجزء 7 - WordPress والبرمجة الموجهة للكائنات: مثال على WordPress - التنفيذ: إدارة WordPress Hooks

نشرت: 2022-02-04

حتى هذه النقطة ، كان التفاعل مع Plugin API يعني استدعاء add_action() و add_filters() في مُنشئ كل فئة.

حتى الآن كان هذا النهج جيدًا بما يكفي ، حيث أبقى الأمور بسيطة وسمح لنا بالتركيز على تعلم المزيد حول البرمجة الموجهة للكائنات باستخدام WordPress. ومع ذلك ، فهي ليست مثالية.

إذا سجل كائن ما جميع خطافاته عند إنشائه ، فإن أشياء مثل اختبار الوحدة تصبح صعبة.

ملاحظة: يجب أن تختبر اختبارات الوحدة كل "وحدة" على حدة. حتى لو لم تكن تكتب اختبارات الوحدة في الوقت الحالي ، فإن كتابة كود قابل للاختبار سيوفر لك الكثير من الوقت لإعادة البناء في وقت لاحق ، إذا قررت كتابة الاختبارات.

مدير هوكس

لنأخذ هذه الخطوة إلى الأمام ونقدم فئة جديدة لإدارة الخطافات الخاصة بنا ، Hooks_Manager . سيكون هذا الفصل مسؤولاً عن تسجيل جميع الخطافات الخاصة بنا. لذلك ، سننشئ فصلًا جديدًا باستخدام طريقة register() .

 class Hooks_Manager { /** * Register the hooks of the given object. * * @param object $object */ public function register( $object ) { // Register the hooks the specified object needs } }

نحتاج إلى واجهة لكل فئة تحتاج إلى تسجيل الخطافات للتنفيذ.

 interface Hooks { /** * Return the actions to register. * * @return array */ public function get_actions(); }

يمكنك التفكير في الواجهة على أنها عقد ، حيث تكون الفئة التي تنفذ تلك الواجهة "ملزمة تعاقديًا" لتنفيذ جميع الطرق المحددة في تلك الواجهة.

على سبيل المثال ، يجب أن تقوم فئة Login_Error التي ترتبط بالإجراء login_head بتنفيذ طريقة get_actions() لواجهة Hooks الخاصة بنا.

 class Login_Error implements Hooks { public function get_actions() { return array( 'login_head' => array( 'add_errors', 10, 1 ), ); } }

تقبل طريقة register() الخاصة بـ Hooks_Manager كائنًا ، وتستدعي طريقة get_actions() الخاصة بها وتسجل جميع إجراءاتها.

 public function register( $object ) { $actions = $object->get_actions(); foreach ( $actions as $action_name => $action_details ) { $method = $action_details[0]; $priority = $action_details[1]; $accepted_args = $action_details[2]; add_action( $action_name, array( $object, $method ), $priority, $accepted_args ); } }

دعنا نضيف طريقة get_filters() إلى واجهتنا ، حتى نتمكن من تسجيل كل من الإجراءات والمرشحات.

 interface Hooks { /** * Return the actions to register. * * @return array */ public function get_actions(); /** * Return the filters to register. * * @return array */ public function get_filters(); }

بالعودة إلى فئة Login_Error ، نحتاج إلى تنفيذ طريقة get_filters() الجديدة هذه.

 class Login_Error implements Hooks { public function get_actions() { return array( 'login_head' => array( 'add_errors', 10, 1 ), ); } public function get_filters() { return array( 'authenticate' => array( 'track_credentials', 10, 3 ), 'shake_error_code' => array( 'add_error_code', 10, 1 ), 'login_errors' => array( 'format_error_message', 10, 1 ), ); } }

سنعيد تسمية طريقة register() الخاصة بـ Hooks_Manager إلى register_actions() . سنضيف أيضًا طريقة register_filters() . ستكون هاتان الطريقتان مسؤولتان عن تسجيل الإجراءات والفلاتر على التوالي.

 class Hooks_Manager { /** * Register the actions of the given object. * * @param object $object */ private function register_actions( $object ) { $actions = $object->get_actions(); foreach ( $actions as $action_name => $action_details ) { $method = $action_details[0]; $priority = $action_details[1]; $accepted_args = $action_details[2]; add_action( $action_name, array( $object, $method ), $priority, $accepted_args ); } } /** * Register the filters of the given object. * * @param object $object */ private function register_filters( $object ) { $filters = $object->get_filters(); foreach ( $filters as $filter_name => $filter_details ) { $method = $filter_details[0]; $priority = $filter_details[1]; $accepted_args = $filter_details[2]; add_filter( $filter_name, array( $object, $method ), $priority, $accepted_args ); } } }

يمكننا الآن إضافة طريقة register() مرة أخرى ، والتي ستستدعي ببساطة كلا من register_actions() و register_filters() .

 class Hooks_Manager { /** * Register an object. * * @param object $object */ public function register( $object ) { $this->register_actions( $object ); $this->register_filters( $object ); } // ...

ماذا لو لم يكن الفصل بحاجة إلى تسجيل كل من الإجراءات والفلاتر؟ تحتوي واجهة Hooks على طريقتين: get_actions() و get_filters() . سيتم إجبار جميع الفئات التي تنفذ تلك الواجهة على تنفيذ كلا الأسلوبين.

 class Cookie_Login implements Hooks { public function get_actions() { return array( 'auth_cookie_bad_username' => array( 'handle_bad_username', 10, 1 ), 'auth_cookie_bad_hash' => array( 'handle_bad_hash', 10, 1 ), 'auth_cookie_valid' => array( 'handle_valid', 10, 2 ), ); } public function get_filters() { return array(); } }

على سبيل المثال ، يجب أن تسجل فئة Cookie_Login الإجراءات فقط ، لكنها مضطرة الآن إلى تنفيذ طريقة get_filters() فقط لإرجاع مصفوفة فارغة.

ينص مبدأ فصل الواجهة (ISP) ، "I" في SOLID ، على ما يلي:

"لا ينبغي إجبار أي عميل على الاعتماد على الأساليب التي لا يستخدمها."

وهذا يعني أن ما نفعله الآن هو بالضبط ما لا ينبغي أن نفعله.

واجهة الفصل

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

 interface Actions { /** * Return the actions to register. * * @return array */ public function get_actions(); }
 interface Filters { /** * Return the filters to register. * * @return array */ public function get_filters(); }

لم نعد بحاجة إلى كل من get_actions() و get_filters() بعد الآن ، يمكننا فقط تنفيذ واجهة Actions والتخلص من get_filters()

 class Cookie_Login implements Actions { public function get_actions() { return array( 'auth_cookie_bad_username' => array( 'handle_bad_username', 10, 1 ), 'auth_cookie_bad_hash' => array( 'handle_bad_hash', 10, 1 ), 'auth_cookie_valid' => array( 'handle_valid', 10, 2 ), ); } }

من ناحية أخرى ، Login_Error ، الذي يحتاج إلى إجراءات وفلاتر ، فقط بتنفيذ كلتا الواجهتين. يمكن للفئات تنفيذ أكثر من واجهة واحدة عن طريق فصلها بفاصلة.

 class Login_Error implements Actions, Filters { public function get_actions() { return array( 'login_head' => array( 'add_errors', 10, 1 ), ); } public function get_filters() { return array( 'authenticate' => array( 'track_credentials', 10, 3 ), 'shake_error_code' => array( 'add_error_code', 10, 1 ), 'login_errors' => array( 'format_error_message', 10, 1 ), ); } }

الآن بعد أن قمنا بفصل واجهتنا ، علينا فقط تحديث طريقة register() Hooks_Manager ) لتعكس التغييرات التي أجريناها.

 class Hooks_Manager { /** * Register an object. * * @param object $object */ public function register( $object ) { if ( $object instanceof Actions ) { $this->register_actions( $object ); } if ( $object instanceof Filters ) { $this->register_filters( $object ); } } // ...

بهذه الطريقة ، نحن نستدعي فقط register_actions() register_filters() ، أو register_filters () فقط ، أو كليهما ، بناءً على الواجهة (الواجهات) التي ينفذها الكائن المحدد.

لاستخدام مدير الخطافات فعليًا:

 $hooks_manager = new Hooks_Manager(); $hooks_manager->register( $login_error ); $hooks_manager->register( $cookie_login );

هذا هو! يمكننا الآن استخدام هذا الكائن لإدارة الخطافات عبر قاعدة الكود بأكملها.

استنتاج

بالطبع ، هناك عدة طرق لإدارة الخطافات الخاصة بك بطريقة موجهة للكائنات ، لقد أظهرنا لك واحدة منها. يجب عليك التجربة والعثور على واحد يناسب احتياجاتك.

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

انقر هنا لقراءة الجزء الثامن في سلسلة البرمجة الشيئية

أنظر أيضا

  • WordPress and Object-Oriented Programming - نظرة عامة
  • الجزء 2 - WordPress والبرمجة الموجهة للكائنات: مثال من العالم الحقيقي
  • الجزء 3 - WordPress والبرمجة الموجهة للكائنات: مثال WordPress - تحديد النطاق
  • الجزء 4 - WordPress والبرمجة الموجهة للكائنات: مثال على WordPress - التصميم
  • الجزء الخامس - البرمجة الموجهة للكائنات و WordPress: مثال على WordPress - التنفيذ: قائمة الإدارة
  • الجزء 6 - WordPress والبرمجة الموجهة للكائنات: مثال على WordPress - التنفيذ: تسجيل الأقسام