Classes & PHP

Astuces en PHP4

Les références

Cette première sous-partie n'est pas réellement une astuce mais plutot une bonne manière de faire pour gérer les objets. En effet, le passage se fait par copie et non par référence. Cependant, dans la majorité des cas, lorsqu'on utilise les objets, le passage par référence est souhaité.

Voici des exemples de code :

// Utilisation du passage par référence
$nb = 7;
function incRef(&$nb)
{
	$nb++;
}
echo $nb."\n";
incRef($nb);
echo $nb."\n";
// Utilisation de l'assignation par référence
$nb = 7;
echo $nb."\n";
$tmp =& $nb;
$tmp++;
echo $nb."\n";
// Utilisation du retour par référence
$nb = 7;
echo $nb."\n";
function &getRef()
{
	global $nb;
	return $nb;
}
$tmp =& getRef();
$tmp++;
echo $nb."\n";

Tout ceci affiche bien à chaque fois 7 puis 8 comme désiré.

Voici son utilisation au sein d'une classe :

class Dog
{
	var $name;
}

class People
{
	var $_dog;

	function setDog(&$dog)
	{
		$this->_dog =& $dog;
	}

	function &getDog()
	{
		return $this->_dog;
	}
}

$dog =& new Dog();
$dog->name = 'Droopy';

$people =& new People();
$people->setDog($dog);
$tmp =& $people->getDog();

$tmp->name = 'Rantanplan';
echo $dog->name;

Comme prévu, le code affiche bien Rantanplan. La commande new Dog() retourne un objet, si l'on veut que cet objet soit directement dans $dog il faut mettre l'opérateur =&. Le simple opérateur = aurait mis une copie dans $dog, ce qui n'est pas génant étant donné car nous n'avons pas accès à l'original.

Il faut noter que l'on ne peut utiliser directement des valeurs pour le passage par référence ; ceci est surtout gênant dans le cas ci-dessous qui NE MARCHE PAS :

class People
{
	var $_dog;

	// ATTENTION : CELA NE MARCHE PAS !
	function People(&$dog = FALSE)
	{
		$this->_dog =& $dog;
	}
}

En effet, il n'est pas possible de définir plusieurs méthodes (et donc constructeurs) de même nom, il faut passer par des valeurs par défaut. Or une valeur n'a pas de référence donc on ne peut la copier. Ce qui nous empêche d'avoir un nombre variable de paramètres avec des objets en référence.

En outre, la copie par référence en utilisant l'opérateur =& ne peut être utilisée pour les variables qui utilisent le mot-clé static.

Destructeur

Bien qu'il ne soit pas nécessaire en PHP de fermer un fichier ou de clore une ressource de base de données, il est parfois utile d'avoir un destructeur. Le destructeur est une méthode appelée lors de la destruction de l'objet. Voici un exemple de son implémentation.

Exemple de desctructeur :

class People
{
	var $_name;

	function People($name)
	{
		// Enregistrement du destructeur
		register_shutdown_function(array(&$this, '_People'));
		$this->_name = $name;
		echo "Création de l'objet People (".$this->_name.")\n";
	}

	function _People()
	{
		echo "Destruction de l'objet People (".$this->_name.")\n";
	}
}

$p1 =& new People('Guy LIGUILI');
$p2 =& new People('Bruce WAYNE');

Ceci produit le résultat suivant :

Création de l'objet People (Guy LIGUILI)
Création de l'objet People (Bruce WAYNE)
Destruction de l'objet People (Guy LIGUILI)
Destruction de l'objet People (Bruce WAYNE)

Cependant, il faut noter que le comportement d'Apache face à cette méthode est différent sous Windows et sous Linux. En effet, sous Linux les méthodes enregistrées via register_shutdown_exception sont appelées après la fermeture de la connexion TCP entre le navigateur et le serveur internet. De ce fait, il est impossible d'afficher quoique ce soit ou d'utiliser les buffeurs car ils sont tous fermés. Toutefois, cela représente un avantage majeur, il est alors possible d'effectuer un long traitement sur le serveur sans qu'aucun utilisateur ne s'en rende compte puisqu'il est déconnecté. Sous windows, l'appel des méthodes se fait avant la fermeture de la connection TCP.