Menu
Coddy logo textTech

__call & __callStatic

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 47 von 91.

Genauso wie __get() und __set() den Zugriff auf Eigenschaften abfangen, fangen die Methoden __call() und __callStatic() Methodenaufrufe ab. Sie werden ausgelöst, wenn Sie eine Methode aufrufen, die nicht existiert oder auf die in einem Objekt oder einer Klasse nicht zugegriffen werden kann.

Die __call()-Methode verarbeitet Instanzmethodenaufrufe. Sie erhält den Methodennamen und ein Array von Argumenten:

<?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");

Ausgabe:

Called 'sendEmail' with: Hello, World

Für statische Methodenaufrufe verwenden Sie __callStatic(). Beachten Sie, dass es als static deklariert werden muss:

<?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");

Ausgabe:

Finding by Email: test@example.com

Diese magischen Methoden sind leistungsstark für die Erstellung von Fluent APIs, die Implementierung von Method Forwarding oder den Aufbau dynamischer Query Builder, bei denen Methodennamen in Datenbankoperationen übersetzt werden. Sie ermöglichen es Ihren Objekten, intelligent auf jeden Methodenaufruf zu reagieren, selbst auf solche, die Sie nicht explizit definiert haben.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen dynamischen API-Client erstellen, der magische Methoden verwendet, um Methodenaufrufe flexibel zu handhaben. Sie werden eine Klasse erstellen, die sowohl Instanz- als auch statische Methodenaufrufe abfängt und diese in aussagekräftige API-ähnliche Antworten übersetzt, ohne jede Methode explizit zu definieren.

Sie werden Ihren Code in zwei Dateien organisieren:

  • ApiClient.php — Erstellen Sie eine ApiClient-Klasse, die API-Interaktionen mithilfe magischer Methoden simuliert. Ihre Klasse sollte eine private $baseUrl-Eigenschaft haben, die über den Konstruktor gesetzt wird. Implementieren Sie zwei magische Methoden:
    • __call() — Verarbeitet Instanzmethodenaufrufe. Wenn eine Methode aufgerufen wird, die mit get beginnt (wie getUsers oder getPosts), extrahieren Sie den Ressourcennamen (den Teil nach "get") und geben Sie "GET [baseUrl]/[resource]: [arguments joined by comma]" zurück. Der Ressourcenname sollte in Kleinbuchstaben umgewandelt werden. Wenn die Methode nicht mit "get" beginnt, geben Sie "Unknown action: [methodName]" zurück.
    • __callStatic() — Verarbeitet statische Methodenaufrufe. Wenn eine Methode aufgerufen wird, die mit create beginnt (wie createUser), extrahieren Sie den Ressourcennamen und geben Sie "POST /[resource]: [arguments joined by comma]" zurück. Der Ressourcenname sollte kleingeschrieben sein. Für Methoden, die mit delete beginnen, geben Sie "DELETE /[resource]: [first argument]" zurück. Für jede andere Methode geben Sie "Static action not supported: [methodName]" zurück.
  • main.php — Binden Sie die ApiClient-Datei ein. Sie erhalten drei Eingaben: eine Basis-URL, einen Ressourcen-Identifikator und einen Wert. Erstellen Sie eine ApiClient-Instanz mit der Basis-URL. Geben Sie dann vier Zeilen aus:
    • Rufen Sie eine dynamische get-Methode auf, wobei der Ressourcen-Identifikator als Suffix des Methodennamens verwendet wird (z. B. wenn die Ressource "Users" ist, rufen Sie getUsers auf) mit dem Wert als Argument
    • Rufen Sie getProducts mit zwei Argumenten auf: "electronics" und "active"
    • Rufen Sie die statische Methode createOrder mit dem Wert als Argument auf
    • Rufen Sie die statische Methode deleteItem mit dem Ressourcen-Identifikator als Argument auf

Die magischen Methoden ermöglichen es Ihrem API-Client, dynamisch auf jeden Methodenaufruf zu reagieren. Anstatt getUsers(), getPosts(), getProducts() und Dutzende weitere zu definieren, verarbeitet eine einzige __call()-Methode sie alle, indem sie den Methodennamen untersucht und die relevanten Informationen extrahiert.

Spickzettel

Die Methode __call() fängt Aufrufe von Instanzmethoden ab, die nicht existieren oder nicht zugänglich sind. Sie erhält den Methodennamen und ein Array mit Argumenten:

<?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");
// Ausgabe: Called 'sendEmail' with: Hello, World

Die Methode __callStatic() fängt statische Methodenaufrufe ab. Sie muss als static deklariert werden:

<?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");
// Ausgabe: Finding by Email: test@example.com

Diese magischen Methoden sind nützlich für die Erstellung von Fluent APIs, die Implementierung von Methodenweiterleitungen oder den Aufbau dynamischer Query-Builder, bei denen Methodennamen in Operationen übersetzt werden.

Probier es selbst

<?php

require_once 'ApiClient.php';

// Eingaben lesen
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Erstellen Sie eine ApiClient-Instanz mit der Basis-URL

// TODO: Rufen Sie eine dynamische get-Methode auf, wobei die Ressource als Suffix des Methodennamens verwendet wird
// Hinweis: Verwenden Sie variable Methodenaufrufe wie $api->{"get" . $resource}($value)

// TODO: Rufen Sie getProducts mit zwei Argumenten auf: "electronics" und "active"

// TODO: Rufen Sie die statische Methode createOrder mit dem Wert als Argument auf
// Hinweis: Verwenden Sie ApiClient::createOrder($value)

// TODO: Rufen Sie die statische Methode deleteItem mit der Ressource als Argument auf

?>
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung