__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, WorldPara 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.comEstos 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.
Desafío
FácilConstruyamos 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 claseApiClientque simule interacciones con una API mediante métodos mágicos. Tu clase debe tener una propiedad privada$baseUrlestablecida 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 porget(comogetUsersogetPosts), 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 porcreate(comocreateUser), 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 pordelete, 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 deApiClientcon la URL base. Después, imprime cuatro líneas:- Llama a un método
getdinámico usando el identificador de recurso como sufijo del nombre del método (por ejemplo, si el recurso es "Users", llama agetUsers) con el valor como argumento - Llama a
getProductscon dos argumentos:"electronics"y"active" - Llama al método estático
createOrdercon el valor como argumento - Llama al método estático
deleteItemcon el identificador de recurso como argumento
- Llama a un método
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
?>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
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - Calculadora de formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeRepaso: colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online