Menu
Coddy logo textTech

__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に対してオブジェクトがインテリジェントに応答できるようにします。

challenge icon

チャレンジ

簡単

メソッド呼び出しを柔軟に処理するために magic methods を使用する dynamic API client を構築しましょう。各メソッドを明示的に定義せずに、instance と static のメソッド呼び出しを intercept し、意味のある API のようなレスポンスに変換する class を作成します。

コードを 2 つのファイルに分けて整理します。

  • ApiClient.php: magic methods を使用して API とのやり取りをシミュレートする ApiClient class を作成します。class には、constructor を通じて設定される private $baseUrl property を持たせます。2 つの magic methods を Implement します。
    • __call(): instance method の呼び出しを処理します。get で始まる method(getUsersgetPosts など)が呼び出された場合、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 を使って ApiClient instance を Create します。次に 4 行を print します。
    • resource identifier を method name の suffix として使用し、dynamic な get method を 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 します

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を呼び出す

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ