Je ne vais pas poser de questions ici, mais juste donner une astuce. Je me suis cassé les dents dessus 2 bonnes heures (et ça fait mal), donc pour éviter de faire le bonheur d'un prochain dentiste, je poste l'astuce ici.
Avec PHP 5, on a des méthodes de surcharges (overloading) des propriétés d'une classe. C'est très intéressant pour les getter/setter (__get et __set), mais ça arrive que PHP 5 nous lance une notice.
D'après les tracks de PHP, le bug est fixé depuis la version 5.2.2. Mais pour tous les autres qui utilisent PHP 5 < 5.2.2, voici l'astuce.
class Overload {
private $_properties = array();
/**
* __set
* Overloading property.
*
* @access public
* @param name string Name.
* @param value string Value.
* @return mixed
*/
public function __set ( $name, $value ) {
$old = null;
if(isset($this->_properties[$name]))
$old = $this->_properties[$name];
$this->_properties[$name] = $value;
return $old;
}
/**
* __get
* Overloading property.
*
* @access public
* @param name string Name.
* @return mixed
*/
public function __get ( $name ) {
if(!isset($this->_properties[$name]))
return null;
return $this->_properties[$name];
}
}
$overload = new Overload;
$overload->string = 'hello world';
echo $overload->string . "\n";
$overload->array = array(
'a' => 'B',
'c' => 'D',
'e' => 'F'
);
foreach($overload->array as $lower => $upper) {
echo $lower . ' ' . $upper . "\n";
}
Résultat attendu :
Code : Tout sélectionner
hello world
a B
c D
e F
Code : Tout sélectionner
hello world
<br />
<b>Notice</b>: Indirect modification of overloaded property Overload::$array has no effect in <b>overload.php</b> on line <b>~55</b><br />
a B
c D
e FJ'ai cru comprendre que le bug ne concerne que les tableaux. J'ai fais des tests sur des objets, je n'ai pas eu de problèmes, mais sinon, venez m'en parler.
L'astuce donc, est de caster (transtyper dans la langue de Molière) la sortie du getter.
/**
* __get
* Overloading property.
*
* @access public
* @param name string Name.
* @return mixed
*/
public function __get ( $name ) {
if(!isset($this->_properties[$name]))
return null;
$cast = gettype($this->_properties[$name]);
switch($cast) {
case 'array':
return (array) $this->_properties[$name];
break;
default:
return $this->_properties[$name];
}
}
Apparement, il serait également de bon ton de déclarer __get en référence, mais cela me donne une erreur, donc je ne le fais pas ici (d'ailleurs, je ne comprends pas trop pourquoi ...).J'ai préféré utiliser un switch plutôt qu'un couple if/else si jamais on doit ajouter le cast pour les objets.
Voilà