Ceci est la seconde partie de PHP: Quelques fonctions méconnues de la programmation objet.
__get, __set, __isset, __unset
PHP permet d’affecter à une instance d’une classe n’importe quelle valeur (presque comme à un tableau de hashage) pour autant que ça ne soit pas une variable privée:
class Objet {};
$obj = new Objet;
$obj->exemple = 1;
echo $obj->exemple . "\n"; // affiche '1'
Lors de l’affectation d’une variable de telle façon, PHP appelle en fait les fonctions __set et __get pour l’affectation et la lecture de la valeur. Il est évidement bien entendu possible de les réécrire afin de définir un nouveau comportement:
class Objet
{
private $data;
public function __construct()
{
$data = array();
}
public function __set($name, $value)
{
echo "Setting $name to $value\n";
$this->data[ $name ] = $value;
}
public function __get($name)
{
echo "returns $name\n";
return $this->data[ $name ];
}
};
require_once("Objet.class.php");
$obj = new Objet;
$obj->priv = 1;
echo $obj->priv;
Cet exemple retournera:
Setting priv to 1
return priv
1
Cela permet de dévier les affectations des variables dans les instances de classe, mais aussi de « protéger » le contenu des classes. Il faut également noter que si l’appel s’effectue pour une variable déclarée privée dans la classe, on sera également redirigé par __get et __set et l’on n’aura plus l’erreur comme quoi on fait appel à une variable privée.
De plus, de la même façon que pour __get et __set, on aura également __isset et __unset qui serviront à redéfinir le comportement lors d’un appel à isset ou à unset.
__call et __callStatic
Comme pour les variables, il est possible d’attraper les appels des fonctions non définies et privées dans les classes, statiques ou non en utilisant __call et __callStatic.
class Objet
{
public function __call($func, $args)
{
echo "Calling $func\n";
}
public static function __callStatic($func, $args)
{
echo "Calling static $func\n";
}
};
class Objet {};
$obj = new Objet;
$obj->exemple = 1; echo $obj->exemple . "\n";
Et à l’exécution:
Calling hello
Calling static hello
Ces deux fonctions, ajoutées aux setters/getters du dessus, permettent de « wrapper » entièrement des instances de classes permettant des utilisations bien plus intéressantes qu’un simple héritage.
__clone
__clone est appelé lorsque l’on crée une copie d’une instance d’objet en appelant clone. Cela résulte à deux instances de la classe totalement indépendante avec le même contenu. Bien que je ne sois pas sûr que clone soit utilisé tous les jours, __clone peut éventuellement être utilisé afin de modifier l’un des deux objets avant ou après le clonage, ou encore de ne pas effectuer ce clonnage afin d’assurer d’avoir un singleton.
__sleep, __wakeup
Finalement, __sleep et __wakeup sont utilisées lors de la sérialisation/désérialisation d’un objet. Elles seront appelées respectivement à l’utilisation de serialize et unserialize. A noter que __sleep doit retourner un array avec la liste des champs à sérialiser.
Comme les courts exemples sont mieux que les longs discours, voici une classe ouvrant un fichier à sa création, le refermant à sa sérialisation, pour le réouvrir à la désérialisation:
class Objet
{
private $file_name = NULL;
private $file_hd = NULL;
public function __construct($file_name)
{
$this->file_name = $file_name;
$this->file_open();
}
public function __destruct()
{
if($this->file_hd !== NULL)
$this->file_close();
}
private function file_open()
{
echo "Opening file\n";
$this->file_hd = fopen($this->file_name, "a+");
}
private function file_close()
{
if(NULL === $this->file_hd)
return false;
echo "Closing file\n";
fclose($this->file_hd);
$this->file_hd = NULL;
}
public function __sleep()
{
echo "* Serialization.\n";
$this->file_close();
return(array('file_name'));
}
public function __wakeup()
{
echo "* Unserialization.\n";
$this->file_open();
}
};
Et testons tout ça:
require_once("Objet.class.php");
$obj = new Objet('helloworld.txt');
$serializedObj = serialize($obj);
unset($obj);
var_dump($serializedObj);
$newObj = unserialize($serializedObj);
echo "Fin du script\n";
On peut vérifier le comportement:
Opening file
* Serialization.
Closing file
string(62) "O:5:"Objet":1:{s:16:"Objetfile_name";s:14:"helloworld.txt";}"
* Unserialization.
Opening file
Fin du script
Closing file
J’espère que quelqu’un aura découvert quelque chose ! :)
Pour ces deux articles, je me suis un peu inspiré d’un article analogue m’ayant poussé à lire un peu plus la doc de PHP: 9 magic methods for php (thinkvitamin.com).
0 Comments.