Menu
Coddy logo textTech

__call e __callStatic

Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 47 di 91.

Proprio come __get() e __set() intercettano l'accesso alle proprietà, i metodi __call() e __callStatic() intercettano le chiamate ai metodi. Vengono attivati quando chiami un metodo che non esiste o non è accessibile su un oggetto o una classe.

Il metodo __call() gestisce le chiamate ai metodi di istanza. Riceve il nome del metodo e un array di argomenti:

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

Output:

Called 'sendEmail' with: Hello, World

Per le chiamate ai metodi statici, usa __callStatic(). Nota che deve essere dichiarato come 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");

Output:

Finding by Email: test@example.com

Questi metodi magici sono potenti per creare API fluenti, implementare l'inoltro dei metodi o creare generatori di query dinamici, in cui i nomi dei metodi si traducono in operazioni sul database. Consentono ai tuoi oggetti di rispondere in modo intelligente a qualsiasi chiamata di metodo, anche a quelle che non hai definito esplicitamente.

challenge icon

Sfida

Facile

Costruiamo un client API dinamico che usa metodi magici per gestire in modo flessibile le chiamate ai metodi. Creerai una classe che intercetta sia le chiamate ai metodi di istanza sia quelle ai metodi statici, trasformandole in risposte significative simili a quelle di un’API senza definire esplicitamente ogni metodo.

Organizzerai il codice in due file:

  • ApiClient.php: crea una classe ApiClient che simula le interazioni con un’API usando metodi magici. La tua classe deve avere una proprietà privata $baseUrl, impostata tramite il costruttore. Implementa due metodi magici:
    • __call(): gestisce le chiamate ai metodi di istanza. Quando viene chiamato un metodo che inizia con get (come getUsers o getPosts), estrai il nome della risorsa (la parte dopo "get") e restituisci "GET [baseUrl]/[resource]: [arguments joined by comma]". Il nome della risorsa deve essere convertito in minuscolo. Se il metodo non inizia con "get", restituisci "Unknown action: [methodName]".
    • __callStatic(): gestisce le chiamate ai metodi statici. Quando viene chiamato un metodo che inizia con create (come createUser), estrai il nome della risorsa e restituisci "POST /[resource]: [arguments joined by comma]". Il nome della risorsa deve essere in minuscolo. Per i metodi che iniziano con delete, restituisci "DELETE /[resource]: [first argument]". Per qualsiasi altro metodo, restituisci "Static action not supported: [methodName]".
  • main.php: includi il file ApiClient. Riceverai tre input: un URL di base, un identificatore di risorsa e un valore. Crea un’istanza di ApiClient con l’URL di base. Poi stampa quattro righe:
    • Chiama un metodo dinamico get, usando l’identificatore di risorsa come suffisso del nome del metodo (ad esempio, se la risorsa è "Users", chiama getUsers), passando il valore come argomento
    • Chiama getProducts con due argomenti: "electronics" e "active"
    • Chiama il metodo statico createOrder passando il valore come argomento
    • Chiama il metodo statico deleteItem passando l’identificatore di risorsa come argomento

I metodi magici permettono al tuo client API di rispondere dinamicamente a qualsiasi chiamata di metodo. Invece di definire getUsers(), getPosts(), getProducts() e decine di altri metodi, un unico metodo __call() li gestisce tutti esaminando il nome del metodo ed estraendo le informazioni pertinenti.

Provalo tu

<?php

require_once 'ApiClient.php';

// Leggi gli input
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Crea un'istanza di ApiClient con l'URL di base

// TODO: Chiama un metodo get dinamico usando resource come suffisso del nome del metodo
// Suggerimento: Usa chiamate a metodi variabili come $api->{"get" . $resource}($value)

// TODO: Chiama getProducts con due argomenti: "electronics" e "active"

// TODO: Chiama il metodo statico createOrder con value come argomento
// Suggerimento: Usa ApiClient::createOrder($value)

// TODO: Chiama il metodo statico deleteItem con resource come argomento

?>
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore PHP online