__call と __callStatic
CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 47/91。
__get() と __set() がプロパティへのアクセスをインターセプトするのと同様に、__call() と __callStatic() メソッドはメソッド呼び出しをインターセプトします。これらは、オブジェクトまたはクラスに存在しない、またはアクセスできないメソッドを呼び出したときにトリガーされます。
__call()メソッドはインスタンスメソッドの呼び出しを処理します。method name と array of arguments を受け取ります:
<?php
class Messenger {
public function __call(string $name, array $arguments): string {
return "Called '$name' with: " . implode(", ", $arguments);
}
}
$msg = new Messenger();
echo $msg->sendEmail("Hello", "World");
出力:
Called 'sendEmail' with: Hello, World静的メソッドの呼び出しには、__callStatic()を使用します。staticとして宣言する必要があることに注意してください。
<?php
class QueryBuilder {
public static function __callStatic(string $name, array $arguments): string {
if (str_starts_with($name, "findBy")) {
$field = substr($name, 6);
return "Finding by $field: " . $arguments[0];
}
return "Unknown method: $name";
}
}
echo QueryBuilder::findByEmail("test@example.com");
出力:
Finding by Email: test@example.comこれらのmagic methodsは、流暢なAPIの作成、method転送の実装、またはmethod名をデータベース操作に変換するdynamicなクエリビルダーの構築に役立ちます。明示的に定義していないものも含め、あらゆるmethod callに対してオブジェクトがインテリジェントに応答できるようにします。
チャレンジ
簡単メソッド呼び出しを柔軟に処理するために magic methods を使用する dynamic API client を構築しましょう。各メソッドを明示的に定義せずに、instance と static のメソッド呼び出しを intercept し、意味のある API のようなレスポンスに変換する class を作成します。
コードを 2 つのファイルに分けて整理します。
ApiClient.php: magic methods を使用して API とのやり取りをシミュレートするApiClientclass を作成します。class には、constructor を通じて設定される private$baseUrlproperty を持たせます。2 つの magic methods を Implement します。__call(): instance method の呼び出しを処理します。getで始まる method(getUsersやgetPostsなど)が呼び出された場合、resource name("get" の after の部分)を extract し、"GET [baseUrl]/[resource]: [arguments joined by comma]"を返します。resource name は lowercase に変換する必要があります。method が "get" で始まらない場合は、"Unknown action: [methodName]"を返します。__callStatic(): static method の呼び出しを処理します。createで始まる method(createUserなど)が呼び出された場合、resource name を extract し、"POST /[resource]: [arguments joined by comma]"を返します。resource name は lowercase にします。deleteで始まる method の場合は、"DELETE /[resource]: [first argument]"を返します。それ以外の method の場合は、"Static action not supported: [methodName]"を返します。
main.php: ApiClient file を include します。3 つの input、つまり base URL、resource identifier、value を受け取ります。base URL を使ってApiClientinstance を Create します。次に 4 行を print します。- resource identifier を method name の suffix として使用し、dynamic な
getmethod を value を argument にして Call します(たとえば resource が "Users" の場合は、getUsersを Call します) getProductsを 2 つの arguments、"electronics"と"active"とともに Call します- static method
createOrderを value を argument にして Call します - static method
deleteItemを resource identifier を argument にして Call します
- resource identifier を method name の suffix として使用し、dynamic な
magic methods によって、API client は任意の method call に dynamic に応答できます。getUsers()、getPosts()、getProducts() など数多くのメソッドを定義する代わりに、1 つの __call() method が method name を調べ、関連する情報を extract することで、それらすべてを処理します。
自分で試してみよう
<?php
require_once 'ApiClient.php';
// 入力を読み取る
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: ベースURLでApiClientのインスタンスを作成する
// TODO: リソースをメソッド名の接尾辞として使用し、動的なgetメソッドを呼び出す
// Hint: $api->{"get" . $resource}($value) のような変数メソッド呼び出しを使用する
// TODO: 2つの引数 "electronics" と "active" でgetProductsを呼び出す
// TODO: 値を引数として静的メソッドcreateOrderを呼び出す
// Hint: ApiClient::createOrder($value) を使用する
// TODO: リソースを引数として静的メソッドdeleteItemを呼び出す
?>このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: PHPオンラインコンパイラ