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 las 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 no es accesible en un objeto o clase.

El método __call() maneja 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 llamadas a métodos estáticos, utiliza __callStatic(). Ten en cuenta 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 APIs fluidas, implementar el reenvío de métodos o construir constructores de consultas dinámicas donde los nombres de los métodos se traducen en operaciones de base de datos. Permiten que tus objetos respondan de manera inteligente a cualquier llamada a un método, incluso a aquellos que no has definido explícitamente.

challenge icon

Desafío

Fácil

Vamos a construir un cliente API dinámico que utiliza métodos mágicos para manejar llamadas a métodos de forma flexible. Crearás una clase que intercepte tanto las llamadas a métodos de instancia como estáticos, traduciéndolas en respuestas significativas de tipo 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 de API utilizando métodos mágicos. Tu clase debe tener una propiedad privada $baseUrl establecida a través del constructor. Implementa dos métodos mágicos:
    • __call() — Maneja las llamadas a métodos de instancia. Cuando se llama a un método que comienza con get (como getUsers o getPosts), extrae el nombre del recurso (la parte después de "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 con "get", devuelve "Unknown action: [methodName]".
    • __callStatic() — Maneja las llamadas a métodos estáticos. Cuando se llama a un método que comienza con 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 con 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. Luego imprime cuatro líneas:
    • Llama a un método get dinámico utilizando 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 API responda a cualquier llamada a un método de forma dinámica. En lugar de definir getUsers(), getPosts(), getProducts() y docenas más, un único método __call() los maneja todos examinando el nombre del método y extrayendo la información relevante.

Hoja de referencia

El método __call() intercepta llamadas a métodos de instancia que no existen o no son accesibles. 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");
// Output: Called 'sendEmail' with: Hello, World

El método __callStatic() intercepta llamadas a métodos estáticos. Debe ser declarado 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");
// Output: Finding by Email: test@example.com

Estos métodos mágicos son útiles para crear APIs fluidas, implementar el reenvío de métodos o construir constructores de consultas dinámicos donde los nombres de los métodos se traducen en operaciones.

Pruébalo tú mismo

<?php

require_once 'ApiClient.php';

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

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

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

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

// TODO: Llamar al método estático createOrder con el valor como argumento
// Sugerencia: Usar ApiClient::createOrder($value)

// TODO: Llamar al método estático deleteItem con el recurso 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