Menu
Coddy logo textTech

__call y __callStatic

Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 47 de 91.

Al igual que __get() y __set() interceptan el acceso a propiedades, los métodos __call() y __callStatic() interceptan las llamadas a métodos. Se activan cuando llamas a un método que no existe o al que no se puede acceder en un objeto o una clase.

El método __call() gestiona las llamadas a métodos de instancia. Recibe el nombre del método y un array de argumentos:

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

Salida:

Called 'sendEmail' with: Hello, World

Para las llamadas a métodos estáticos, usa __callStatic(). Observa que debe declararse como 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");

Salida:

Finding by Email: test@example.com

Estos métodos mágicos son potentes para crear API fluidas, implementar el reenvío de métodos o crear constructores de consultas dinámicas en los que los nombres de los métodos se traducen en operaciones de base de datos. Permiten que tus objetos respondan de forma inteligente a cualquier llamada a un método, incluso a aquellas que no hayas definido explícitamente.

challenge icon

Desafío

Fácil

Construyamos un cliente de API dinámico que use métodos mágicos para gestionar las llamadas a métodos de forma flexible. Crearás una clase que intercepte tanto las llamadas a métodos de instancia como a métodos estáticos, traduciéndolas en respuestas significativas similares a las de una API sin definir cada método explícitamente.

Organizarás tu código en dos archivos:

  • ApiClient.php: Crea una clase ApiClient que simule interacciones con una API mediante métodos mágicos. Tu clase debe tener una propiedad privada $baseUrl establecida mediante el constructor. Implementa dos métodos mágicos:
    • __call(): Gestiona las llamadas a métodos de instancia. Cuando se llama a un método que comienza por get (como getUsers o getPosts), extrae el nombre del recurso (la parte posterior a "get") y devuelve "GET [baseUrl]/[resource]: [arguments joined by comma]". El nombre del recurso debe convertirse a minúsculas. Si el método no comienza por "get", devuelve "Unknown action: [methodName]".
    • __callStatic(): Gestiona las llamadas a métodos estáticos. Cuando se llama a un método que comienza por create (como createUser), extrae el nombre del recurso y devuelve "POST /[resource]: [arguments joined by comma]". El nombre del recurso debe estar en minúsculas. Para los métodos que comienzan por delete, devuelve "DELETE /[resource]: [first argument]". Para cualquier otro método, devuelve "Static action not supported: [methodName]".
  • main.php: Incluye el archivo ApiClient. Recibirás tres entradas: una URL base, un identificador de recurso y un valor. Crea una instancia de ApiClient con la URL base. Después, imprime cuatro líneas:
    • Llama a un método get dinámico usando el identificador de recurso como sufijo del nombre del método (por ejemplo, si el recurso es "Users", llama a getUsers) con el valor como argumento
    • Llama a getProducts con dos argumentos: "electronics" y "active"
    • Llama al método estático createOrder con el valor como argumento
    • Llama al método estático deleteItem con el identificador de recurso como argumento

Los métodos mágicos permiten que tu cliente de API responda dinámicamente a cualquier llamada a un método. En lugar de definir getUsers(), getPosts(), getProducts() y docenas más, un único método __call() se encarga de todos ellos examinando el nombre del método y extrayendo la información pertinente.

Pruébalo tú mismo

<?php

require_once 'ApiClient.php';

// Leer entradas
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Crea una instancia de ApiClient con la URL base

// TODO: Llama a un método get dinámico usando el resource como sufijo del nombre del método
// Hint: Usa llamadas a métodos variables como $api->{"get" . $resource}($value)

// TODO: Llama a getProducts con dos argumentos: "electronics" y "active"

// TODO: Llama al método estático createOrder con el value como argumento
// Hint: Usa ApiClient::createOrder($value)

// TODO: Llama al método estático deleteItem con el resource como argumento

?>
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de PHP online