パート7– WordPressとオブジェクト指向プログラミング:WordPressの例–実装:WordPressフックの管理
公開: 2022-02-04これまで、プラグインAPIとの対話は、各クラスのコンストラクターでadd_action 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_head
アクションにフックするLogin_Error
クラスは、 Hooks
インターフェイスのget_actions()
メソッドを実装する必要があります。
class Login_Error implements Hooks { public function get_actions() { return array( 'login_head' => array( 'add_errors', 10, 1 ), ); } }
Hooks_Manager
のregister()
メソッドは、オブジェクトを受け取り、その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 ), ); } }
Hooks_Manager
のregister_actions()
register()
メソッドの名前をregister_actions()に変更します。 また、 register_filters()
メソッドを追加します。 これらの2つのメソッドは、それぞれアクションとフィルターの登録を担当します。
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_actions()
とget_filters()
)の2つのメソッドが含まれています。 そのインターフェイスを実装するすべてのクラスは、両方のメソッドを実装するように強制されます。
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()
メソッドを実装する必要があります。
SOLIDの「I」であるインターフェイス分離の原則(ISP)は、次のように述べています。
「クライアントが使用しないメソッドに依存することを強制されるべきではありません。」
私たちが今していることは、まさに私たちがしてはいけないことであるということを意味します。
インターフェイス分離
これを修正するには、インターフェースをより小さく、より具体的なものに分割して、クラスが関心のあるメソッドについてのみ知る必要があるようにします。
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 ), ); } }
インターフェイスを分離したので、変更を反映するためにHooks_Manager
のregister()
メソッドを更新する必要があります。
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_actions()
、またはその両方を条件付きで呼び出します。
フックマネージャーを実際に使用するには:
$hooks_manager = new Hooks_Manager(); $hooks_manager->register( $login_error ); $hooks_manager->register( $cookie_login );
それでおしまい! これで、そのオブジェクトを使用して、コードベース全体のフックを管理できます。
結論
もちろん、オブジェクト指向の方法でフックを管理する方法はいくつかありますが、そのうちの1つを紹介しました。 実験して、ニーズに合ったものを見つける必要があります。
このシリーズの最後のパートでは、オブジェクト指向の方法でオプションを処理する方法、カプセル化、抽象化、およびクラスを分離して拡張が容易な柔軟なプラグインを作成する方法について説明します。
オブジェクト指向プログラミングシリーズのパート8を読むには、ここをクリックしてください
関連項目
- WordPressとオブジェクト指向プログラミング–概要
- パート2– WordPressとオブジェクト指向プログラミング:実際の例
- パート3– WordPressとオブジェクト指向プログラミング:ΑWordPressの例–スコープの定義
- パート4– WordPressとオブジェクト指向プログラミング:WordPressの例–デザイン
- パート5– WordPressとオブジェクト指向プログラミング:WordPressの例–実装:管理メニュー
- パート6– WordPressとオブジェクト指向プログラミング:WordPressの例–実装:セクションの登録