PHP
Méthodes magiques
Recherche…
__get (), __set (), __isset () et __unset ()
Chaque fois que vous essayez de récupérer un certain champ d'une classe comme ceci:
$animal = new Animal();
$height = $animal->height;
PHP appelle la méthode magique __get($name)
, avec $name
égal à "height"
dans ce cas. Écrire dans un champ de classe comme ceci:
$animal->height = 10;
Invoquera la méthode magique __set($name, $value)
, avec $name
égal à "height"
et $value
égal à 10
.
PHP a également deux fonctions isset()
, qui vérifient si une variable existe et unset()
, ce qui détruit une variable. Vérifier si un champ d'objets est défini comme ceci:
isset($animal->height);
Invoquera la fonction __isset($name)
sur cet objet. Détruire une variable comme ça:
unset($animal->height);
Invoquera la fonction __unset($name)
sur cet objet.
Normalement, lorsque vous ne définissez pas ces méthodes sur votre classe, PHP récupère simplement le champ tel qu'il est stocké dans votre classe. Cependant, vous pouvez remplacer ces méthodes pour créer des classes pouvant contenir des données comme un tableau, mais utilisables comme un objet:
class Example {
private $data = [];
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __get($name) {
if (!array_key_exists($name, $this->data)) {
return null;
}
return $this->data[$name];
}
public function __isset($name) {
return isset($this->data[$name]);
}
public function __unset($name) {
unset($this->data[$name]);
}
}
$example = new Example();
// Stores 'a' in the $data array with value 15
$example->a = 15;
// Retrieves array key 'a' from the $data array
echo $example->a; // prints 15
// Attempt to retrieve non-existent key from the array returns null
echo $example->b; // prints nothing
// If __isset('a') returns true, then call __unset('a')
if (isset($example->a)) {
unset($example->a));
}
fonction empty () et méthodes magiques
Notez que l'appel à empty()
sur un attribut de classe invoquera __isset()
car, comme l'indique le manuel PHP:
empty () est essentiellement l'équivalent concis de ! isset ($ var) || $ var == false
__construct () and __destruct ()
__construct()
est la méthode magique la plus courante en PHP, car elle est utilisée pour configurer une classe lorsqu'elle est initialisée. Le contraire de la méthode __construct()
est la méthode __destruct()
. Cette méthode est appelée lorsqu'il n'y a plus de références à un objet que vous avez créé ou lorsque vous forcez sa suppression. La récupération de mémoire de PHP va nettoyer l'objet en appelant d'abord son destructeur, puis en le retirant de la mémoire.
class Shape {
public function __construct() {
echo "Shape created!\n";
}
}
class Rectangle extends Shape {
public $width;
public $height;
public function __construct($width, $height) {
parent::__construct();
$this->width = $width;
$this->height = $height;
echo "Created {$this->width}x{$this->height} Rectangle\n";
}
public function __destruct() {
echo "Destroying {$this->width}x{$this->height} Rectangle\n";
}
}
function createRectangle() {
// Instantiating an object will call the constructor with the specified arguments
$rectangle = new Rectangle(20, 50);
// 'Shape Created' will be printed
// 'Created 20x50 Rectangle' will be printed
}
createRectangle();
// 'Destroying 20x50 Rectangle' will be printed, because
// the `$rectangle` object was local to the createRectangle function, so
// When the function scope is exited, the object is destroyed and its
// destructor is called.
// The destructor of an object is also called when unset is used:
unset(new Rectangle(20, 50));
__toString ()
Chaque fois qu'un objet est traité comme une chaîne, la __toString()
est appelée. Cette méthode doit renvoyer une représentation sous forme de chaîne de la classe.
class User {
public $first_name;
public $last_name;
public $age;
public function __toString() {
return "{$this->first_name} {$this->last_name} ($this->age)";
}
}
$user = new User();
$user->first_name = "Chuck";
$user->last_name = "Norris";
$user->age = 76;
// Anytime the $user object is used in a string context, __toString() is called
echo $user; // prints 'Chuck Norris (76)'
// String value becomes: 'Selected user: Chuck Norris (76)'
$selected_user_string = sprintf("Selected user: %s", $user);
// Casting to string also calls __toString()
$user_as_string = (string) $user;
__invoquer()
Cette méthode magique est appelée lorsque l'utilisateur essaie d'appeler un objet en tant que fonction. Les cas d'utilisation possibles peuvent inclure certaines approches comme la programmation fonctionnelle ou certains rappels.
class Invokable
{
/**
* This method will be called if object will be executed like a function:
*
* $invokable();
*
* Args will be passed as in regular method call.
*/
public function __invoke($arg, $arg, ...)
{
print_r(func_get_args());
}
}
// Example:
$invokable = new Invokable();
$invokable([1, 2, 3]);
// optputs:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
__call () et __callStatic ()
__call()
et __callStatic()
sont appelés lorsque quelqu'un appelle une méthode d'objet inexistante dans un contexte objet ou statique.
class Foo
{
/**
* This method will be called when somebody will try to invoke a method in object
* context, which does not exist, like:
*
* $foo->method($arg, $arg1);
*
* First argument will contain the method name(in example above it will be "method"),
* and the second will contain the values of $arg and $arg1 as an array.
*/
public function __call($method, $arguments)
{
// do something with that information here, like overloading
// or something generic.
// For sake of example let's say we're making a generic class,
// that holds some data and allows user to get/set/has via
// getter/setter methods. Also let's assume that there is some
// CaseHelper which helps to convert camelCase into snake_case.
// Also this method is simplified, so it does not check if there
// is a valid name or
$snakeName = CaseHelper::camelToSnake($method);
// Get get/set/has prefix
$subMethod = substr($snakeName, 0, 3);
// Drop method name.
$propertyName = substr($snakeName, 4);
switch ($subMethod) {
case "get":
return $this->data[$propertyName];
case "set":
$this->data[$propertyName] = $arguments[0];
break;
case "has":
return isset($this->data[$propertyName]);
default:
throw new BadMethodCallException("Undefined method $method");
}
}
/**
* __callStatic will be called from static content, that is, when calling a nonexistent
* static method:
*
* Foo::buildSomethingCool($arg);
*
* First argument will contain the method name(in example above it will be "buildSomethingCool"),
* and the second will contain the value $arg in an array.
*
* Note that signature of this method is different(requires static keyword). This method was not
* available prior PHP 5.3
*/
public static function __callStatic($method, $arguments)
{
// This method can be used when you need something like generic factory
// or something else(to be honest use case for this is not so clear to me).
print_r(func_get_args());
}
}
Exemple:
$instance = new Foo();
$instance->setSomeState("foo");
var_dump($instance->hasSomeState()); // bool(true)
var_dump($instance->getSomeState()); // string "foo"
Foo::exampleStaticCall("test");
// outputs:
Array
(
[0] => exampleCallStatic
[1] => test
)
__sleep () et __wakeup ()
__sleep
et __wakeup
sont des méthodes liées au processus de sérialisation. serialize
vérifie si une classe a une méthode __sleep
. Si c'est le cas, il sera exécuté avant toute sérialisation. __sleep
est censé retourner un tableau des noms de toutes les variables d'un objet à sérialiser.
__wakeup
à son tour sera exécuté par unserialize
s'il est présent dans la classe. Son intention est de rétablir les ressources et autres éléments nécessaires à l'initialisation lors de la désérialisation.
class Sleepy {
public $tableName;
public $tableFields;
public $dbConnection;
/**
* This magic method will be invoked by serialize function.
* Note that $dbConnection is excluded.
*/
public function __sleep()
{
// Only $this->tableName and $this->tableFields will be serialized.
return ['tableName', 'tableFields'];
}
/**
* This magic method will be called by unserialize function.
*
* For sake of example, lets assume that $this->c, which was not serialized,
* is some kind of a database connection. So on wake up it will get reconnected.
*/
public function __wakeup()
{
// Connect to some default database and store handler/wrapper returned into
// $this->dbConnection
$this->dbConnection = DB::connect();
}
}
__les informations de débogage()
Cette méthode est appelée par
var_dump()
lors du vidage d'un objet pour obtenir les propriétés à afficher. Si la méthode n'est pas définie sur un objet, toutes les propriétés publiques, protégées et privées seront affichées. - PHP Manual
class DeepThought {
public function __debugInfo() {
return [42];
}
}
var_dump(new DeepThought());
L'exemple ci-dessus affichera:
class DeepThought#1 (0) {
}
var_dump(new DeepThought());
L'exemple ci-dessus affichera:
class DeepThought#1 (1) {
public ${0} =>
int(42)
}
__cloner()
__clone
est __clone
à l'aide du mot clé clone
. Il est utilisé pour manipuler l'état de l'objet lors du clonage, une fois que l'objet a été cloné.
class CloneableUser
{
public $name;
public $lastName;
/**
* This method will be invoked by a clone operator and will prepend "Copy " to the
* name and lastName properties.
*/
public function __clone()
{
$this->name = "Copy " . $this->name;
$this->lastName = "Copy " . $this->lastName;
}
}
Exemple:
$user1 = new CloneableUser();
$user1->name = "John";
$user1->lastName = "Doe";
$user2 = clone $user1; // triggers the __clone magic method
echo $user2->name; // Copy John
echo $user2->lastName; // Copy Doe