__call & __callStatic
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 47 sur 91.
Tout comme __get() et __set() interceptent l'accès aux propriétés, les méthodes __call() et __callStatic() interceptent les appels de méthodes. Elles sont déclenchées lorsque vous appelez une méthode qui n'existe pas ou qui est inaccessible sur un objet ou une classe.
La méthode __call() gère les appels de méthodes d'instance. Elle reçoit le nom de la méthode et un tableau d'arguments :
<?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");
Sortie :
Called 'sendEmail' with: Hello, WorldPour les appels de méthodes statiques, utilisez __callStatic(). Notez qu'elle doit être déclarée comme 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");
Sortie :
Finding by Email: test@example.comCes méthodes magiques sont puissantes pour créer des API fluides, implémenter le transfert de méthodes ou construire des générateurs de requêtes dynamiques où les noms de méthodes se traduisent en opérations de base de données. Elles permettent à vos objets de répondre intelligemment à n'importe quel appel de méthode, même ceux que vous n'avez pas explicitement définis.
Défi
FacileConstruisons un client API dynamique qui utilise des méthodes magiques pour gérer les appels de méthodes de manière flexible. Vous allez créer une classe qui intercepte à la fois les appels de méthodes d'instance et statiques, en les traduisant en réponses de type API significatives sans définir chaque méthode explicitement.
Vous organiserez votre code sur deux fichiers :
ApiClient.php— Créez une classeApiClientqui simule des interactions API en utilisant des méthodes magiques. Votre classe doit avoir une propriété privée$baseUrldéfinie via le constructeur. Implémentez deux méthodes magiques :__call()— Gère les appels de méthodes d'instance. Lorsqu'une méthode commençant pargetest appelée (commegetUsersougetPosts), extrayez le nom de la ressource (la partie après "get") et retournez"GET [baseUrl]/[resource]: [arguments joined by comma]". Le nom de la ressource doit être converti en minuscules. Si la méthode ne commence pas par "get", retournez"Unknown action: [methodName]".__callStatic()— Gère les appels de méthodes statiques. Lorsqu'une méthode commençant parcreateest appelée (commecreateUser), extrayez le nom de la ressource et retournez"POST /[resource]: [arguments joined by comma]". Le nom de la ressource doit être en minuscules. Pour les méthodes commençant pardelete, retournez"DELETE /[resource]: [first argument]". Pour toute autre méthode, retournez"Static action not supported: [methodName]".
main.php— Incluez le fichier ApiClient. Vous recevrez trois entrées : une URL de base, un identifiant de ressource et une valeur. Créez une instance deApiClientavec l'URL de base. Ensuite, affichez quatre lignes :- Appelez une méthode
getdynamique en utilisant l'identifiant de ressource comme suffixe du nom de la méthode (par exemple, si la ressource est "Users", appelezgetUsers) avec la valeur comme argument - Appelez
getProductsavec deux arguments :"electronics"et"active" - Appelez la méthode statique
createOrderavec la valeur comme argument - Appelez la méthode statique
deleteItemavec l'identifiant de ressource comme argument
- Appelez une méthode
Les méthodes magiques permettent à votre client API de répondre dynamiquement à n'importe quel appel de méthode. Au lieu de définir getUsers(), getPosts(), getProducts(), et des dizaines d'autres, une seule méthode __call() les gère toutes en examinant le nom de la méthode et en extrayant les informations pertinentes.
Aide-mémoire
La méthode __call() intercepte les appels de méthodes d'instance qui n'existent pas ou sont inaccessibles. Elle reçoit le nom de la méthode et un tableau d'arguments :
<?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");
// Résultat : Called 'sendEmail' with: Hello, World
La méthode __callStatic() intercepte les appels de méthodes statiques. Elle doit être déclarée comme 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");
// Résultat : Finding by Email: test@example.com
Ces méthodes magiques sont utiles pour créer des API fluides, implémenter le transfert de méthodes ou construire des générateurs de requêtes dynamiques où les noms de méthodes se traduisent en opérations.
Essayez vous-même
<?php
require_once 'ApiClient.php';
// Lire les entrées
$baseUrl = trim(fgets(STDIN));
$resource = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Créer une instance d'ApiClient avec l'URL de base
// TODO: Appeler une méthode get dynamique en utilisant la ressource comme suffixe du nom de la méthode
// Astuce : Utilisez des appels de méthode variables comme $api->{"get" . $resource}($value)
// TODO: Appeler getProducts avec deux arguments : "electronics" et "active"
// TODO: Appeler la méthode statique createOrder avec la valeur comme argument
// Astuce : Utilisez ApiClient::createOrder($value)
// TODO: Appeler la méthode statique deleteItem avec la ressource comme argument
?>Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie