最近、「php Core Technology and Best Practices」という本を読んでいます。この本の最初の章では、__call() メソッドを使用して単純な文字列チェーン操作を実装できると述べています。たとえば、次の例では文字列をフィルター処理します。長さの演算は通常次のように記述されます:
それでは以下のような書き方は実現可能でしょうか?
今すぐ試してみましょう。
チェーン操作とは、端的に言えば、実際にはオブジェクトをチェーンで呼び出す方法です。文字列チェーン操作を実装する必要があるため、文字列クラスを実装してから、このクラスのオブジェクトを呼び出す必要があります。 String クラスに対する私の期待は次のとおりです。(1) オブジェクトを作成するときに、文字列をオブジェクトのプロパティに割り当てることができ、このプロパティにアクセスして値を読み取ることができます。(2) trim( を呼び出すことができます。 ) と strlen( ) メソッド; (3) このように $str->trim()->strlen() メソッドを呼び出すこともできます。
上記の項目 (1) は、文字列クラスの基本的な要件です。まずこれを実装しましょう:
次のことを試すことができます:
次に項目 2 を見て、最初に $str->trim() を実装し、本のアイデアを参照してください: __call メソッドをトリガーしてから call_user_func を実行します。コードは次のとおりです:
テスト済み:
結果は以下の通りです:
上記で注意する必要があるのは 12 行目です: $this->value = call_user_func($name, $this->value, $args[0]);$ name はコールバック関数の名前 (ここでは、trim) で、最後の 2 つはコールバック関数 (tim) のパラメーターです。パラメーターの順序を逆にしないでください。 $args は配列なので注意が必要です。
Strlen() も記事 2 で実装する必要があります。現時点では、上記のコードの 13 行目が非常に重要です: return $this; その機能は、12 行目での Trim() 処理を呼び出すことです。文字列を取得し、value 属性を再割り当てしてから、現在のオブジェクトの参照を返すことで、オブジェクト内の他のメソッドが属性値に対して継続的な操作を実行できるようになり、チェーン操作が実現されます。 $str->strlen() は次のように実装されます:
テスト済み:
結果:
チェーン操作:
結果:
この時点で、この記事は終了しているはずです。しかし、よく考えてみると、__call()メソッドを使わなくても連鎖操作が実現できることが分かりました。以下は __call() を使用しない実装です:
操作を連鎖させる鍵は、操作の完了後に $this を返すことです。
さらに、この記事は庭のこの記事に触発され、call_user_func() の実装を call_user_func_array() に置き換え、__call() メソッドを次のように変更しました。
効果は上記の __call() メソッドと同じなので、コードは以前の実装よりも洗練されているように見えます。
概要:
__call() は、オブジェクトがアクセスできないメソッドを呼び出すときにトリガーされるため、クラスの動的メソッドの作成を実現し、PHP のメソッドのオーバーロード機能を実現できますが、実際には構文の糖衣です (__construct() メソッドはまた)。
では、__call() のような構文糖がなければ、動的メソッドやチェーン操作の作成は実現できるでしょうか?これには、クラスメソッドが存在し、呼び出せるかどうかが含まれると思います。これは、method_exists、is_callable、get_class_methods などのメソッドを使用して実現できます。また、オブジェクトの作成時に属性に値を割り当てる (初期化) ことも含まれます。構文シュガーは確かに便利ですが、必須ではありません。時間があるときにもう一度勉強しましょう。