Les nouveautés de PHP 5.3

Et comment migrer de PHP 5.2 vers PHP 5.3


précédentsommairesuivant

I. Modifications à l'interface objet

Cette section est une traduction de : http://www.ibm.com/developerworks/opensource/library/os-php-5.3new1/

I-A. PHP 5 et la programmation orientée objet

Lorsque PHP 5 fut diffusé en 2004, c'était un très grand bond en avant par rapport à ce qu'était PHP 4 et à sa conception de programmation orientée objet (POO). Elle ajoutait plusieurs améliorations nécessaires comme la visibilité dans les classes, de véritables constructeurs et destructeurs, une mesure de suggestion de types et une API d'introspection de classes. Elle ouvrait la porte à de la POO avancée en PHP, et vous permettait d'implémenter plus aisément de nombreux motifs de conception ainsi que des API et des classes mieux conçues.

Dans PHP 5.3, de nombreux ajouts ont été faits pour améliorer la POO. Ces améliorations sont faites dans le domaine de la syntaxe du langage et des performances. Pour commencer, voyons les nouvelles fonctionnalités disponibles avec les méthodes et les propriétés statiques.

I-A-1. Amélioration de la gestion des méthodes et des propriétés statiques

Une amélioration utile de PHP 5 était la possibilité de définir une propriété ou une méthode comme étant statique (PHP 4 connaissait les propriétés et les méthodes statiques dans les classes, mais n'avait pas la possibilité de dire que la propriété ou la classe était conçue pour un accès statique). L'accès statique est particulièrement utile pour implémenter le motif de conception « Singleton », d'après lequel il n'existe qu'une seule instance de la classe.

PHP 5.3 ajoute diverses fonctionnalités pour améliorer le support des propriétés et des méthodes statiques dans une classe. Tout d'abord, nous allons voir la nouvelle méthode magique : __callStatic()

I-A-2. La méthode magique __callStatic()

PHP 5 possède plusieurs méthodes spécifiques aux classes, connues sous le nom de méthodes magiques. Lorsqu'elles sont définies dans la classe, ces méthodes apportent des fonctionnalités spéciales et elles permettent la surcharge (la capacité de permettre à une méthode d'accepter différents types de paramètres) ainsi que le polymorphisme (la capacité de permettre à différents types d'utiliser la même interface). Elles ouvrent également la porte à l'utilisation aisée de différents types de POO et de motifs de conception avec PHP.

Dans PHP 5.3, une nouvelle méthode magique est ajoutée : __callStatic(). Elle fonctionne de manière similaire à la méthode magique __call(), qui est prévue pour gérer les appels de méthodes qui ne sont pas définies ou pas visibles dans une classe. Cependant, __callStatic() est conçue pour gérer les appels statiques, ce qui nous donne la possibilité de mieux prévoir notre surcharge de méthodes. Voici un exemple d'utilisation de cette méthode :

Listing 1. Exemple d'utilisation de __callStatic() contre __call()
Sélectionnez
class Foo 
{ 
    public static function __callStatic($name, $args) 
    { 
        echo "La méthode $name est appelée de manière statique"; 
    } 

    public function __call($name, $args) 
    { 
        echo "La méthode $name est appelée"; 
    } 
} 

Foo::chien();       // affiche "La méthode chien est appelée de manière statique" 
$foo = new Foo; 
$foo->chien();      // affiche "La méthode chien est appelée" 

La déclaration de la méthode __callStatic() doit être public et static. De même, la méthode __call() doit également être définie public, comme toutes les méthodes magiques.

I-A-3. Appels statiques dynamiques

Les variables de variables sont une fonctionnalité sympathique de PHP. Cela signifie que vous pouvez utiliser la valeur « chaîne » d'une variable pour spécifier le nom d'une autre variable. En d'autres mots, vous pourriez faire quelque chose comme :

Listing 2. Variables de variables
Sélectionnez
$x = 'y';
$$x = 'z';
echo $x;  // affiche 'y'
echo $y;  // affiche 'z'
echo $$x; // affiche 'z'

Le même concept peut être utilisé pour les fonctions, ou même pour les méthodes de classes, comme le montre cet exemple :

Listing 3. Noms variables de fonctions et de méthodes de classes
Sélectionnez
class Chien 
{ 
    public function aboyer() 
    { 
        echo "Ouah !"; 
    } 
} 

$class = 'Chien' ;
$action = 'aboyer'; 
$x = new $class(); // instancie la classe 'Chien' 
$x->$action();     // affiche "Ouah !" 

Une nouveauté de PHP 5.3 est la possibilité d'avoir le nom de la classe en tant que variable lors d'un appel statique, ce qui offre quelques possibilités comme démontré ci-dessous :

Listing 4. Nom variable de classe
Sélectionnez
class Chien 
{ 
    public static function aboyer() 
    { 
         echo "Ouah !"; 
    } 
} 

$class = 'Chien'; 
$action = 'aboyer'; 
$class::$action();  //affiche "Ouah !" 

Cet ajout complète la fonctionnalité des variables variables de PHP en leur permettant d'être utilisées dans à peu près toutes les situations avec PHP.

Voyons maintenant une autre amélioration utile de l'utilisation de méthodes et de propriétés statiques : « late static binding ».

I-B. Liaison statique différée (late static binding)

L'une des choses les plus agaçantes avec PHP avant 5.3 est comment les propriétés et les membres statiques sont gérés. Jusqu'à présent, les références statiques, comme celles faites avec self ou __CLASS__, étaient résolues dans la même portée que celle dans laquelle la fonction était définie. Le problème est que la référence est incorrecte si la classe est étendue et si l'appel est fait depuis la nouvelle classe fille. Late static binding a été ajouté à PHP 5.3 pour résoudre ce problème. Pour mieux illustrer, créons une classe avec une méthode statique :

Listing 5. Classe Foo avec une méthode statique test()
Sélectionnez
class Foo 
{ 
    protected static $name = 'Foo'; 

    public static function test() 
    { 
        return self::$name; 
    } 
} 

Étendons cette classe. Nous allons définir de nouveau la propriété $name dans la classe fille :

Listing 6. La classe fille Bar étend la classe parent Foo
Sélectionnez
    class Bar extends Foo
    {
       protected static $name = 'Bar';
    }

Nous faisons alors l'appel statique en listing 7

Listing 7. Appel statique à la méthode test()
Sélectionnez
echo Bar::test(); 

Ce qui est affiché par cet appel, est la chaîne « Foo ». C'est à cause de la référence self::$name faite dans la méthode test() dans la classe Foo. La liaison a lieu de cette manière parce que c'est à cet endroit que la méthode est définie.

PHP 5.3 ajoute le mot clef static pour permettre de faire cette référence avec la classe actuelle. Ainsi, faites le changement dans la classe Foo ci-dessus pour utiliser ce mot clef en Listing 8, et nous verrons que « Bar » sera affiché à la place :

Listing 8. Using the static keyword
Sélectionnez
class Foo 
{ 
    protected static $name = 'Foo'; 

    public static function test() 
    { 
        return static::$name; 
    } 
} 

class Bar extends Foo
{ 
    protected static $name = 'Bar'; 
} 

echo Bar::test(); // affiche 'Bar'

Le mot clef static ne fonctionne pas de la même manière que ce code fonctionnerait en contexte non statique. Cela signifie que les règles normales d'héritage ne fonctionnent pas pour les appels statiques. Le mot clef static va simplement essayer de résoudre l'appel dans la classe actuelle plutôt que dans la classe dans laquelle la fonction est définie. Il est important de bien le comprendre.

Maintenant que nous avons vu quelques améliorations avec les propriétés et les méthodes statiques, voyons quelques nouvelles classes ajoutées à une partie très utile de PHP 5 : la Standard PHP Library.

I-C. Standard PHP Library

La Standard PHP Library (SPL) est un ensemble d'interfaces et de classes ajoutées en PHP 5 et conçues pour résoudre des problèmes courants. Ces problèmes incluent le besoin d'un objet que l'on puisse parcourir par itérations, donner à un objet le comportement d'un tableau ou implémenter une liste liée. L'avantage d'utiliser ces classes et ces méthodes est qu'elles sont natives à PHP, ce qui signifie qu'elles sont plus rapides que si elles étaient implémentées en PHP. Dans de nombreux cas, elles permettent également d'utiliser beaucoup de fonctions internes de PHP directement sur ces objets, comme l'interface Iterator qui est compatible avec la structure foreach pour parcourir un objet.

PHP 5.3 ajoute quelques classes supplémentaires à la SPL. Nous avons parlé plus haut de la liste doublement chaînée, c'est la classe SplDoublyLinkedList dans la SPL. Elle est utilisée par deux autres nouvelles classes de la SPL : SplStack, qui implémente une pile, et SplQueue, qui implémente une file.

Voyons comment utiliser la classe SplStack pour implémenter une pile :

Listing 9. Utiliser SplStack
Sélectionnez
$stack = new SplStack(); 

// ajouter de nouveaux éléments à la pile
$stack->push('a'); 
$stack->push('b'); 
$stack->push('c'); 

// voir combien d'éléments sont dans la pile
echo count($stack); // renvoie 3 

// itérer sur les éléments de la pile
foreach ( $stack as $item ) 
    echo "[$item],";   
// affiche : [c],[b],[a]

// supprimer un élément du dessus de la pile
echo $stack->pop(); // renvoie 'c' 

// voir combien d'éléments sont dans la pile maintenant
echo count($stack); // renvoie 2

SplQueue fonctionne de manière similaire, mais comme une file le ferait (« premier élément entré, premier élément sorti » au lieu de «dernier élément entré, premier élément sorti » comme la pile). De plus, il existe une implémentation tas (SplHeap) ainsi que certaines implémentations de files et de tas pour des situations précises (SplMinHeap, SplMaxHeap et SplPriorityQueue).

Un autre ajout est la classe SplFixedArray qui, comme le nom le suggère, est une implémentation de tableau à taille fixe. Elle est très rapide ; en fait, elle est tellement rapide qu'elle a été mesurée pour un gain de 10 à 30% par rapport à l'implémentation Array native de PHP. Ce gain de vitesse est dû au fait que le tableau est de taille fixe, contrairement au type Array natif de PHP, et que les indexes non numériques ne sont pas permis. Le Listing 10 montre son utilisation :

Listing 10. SplFixedArray
Sélectionnez
$array = new SplFixedArray(3); 
$array[0] = 'chien'; 
$array[1] = 'chat'; 
$array[2] = 'oiseau'; 
$array->setSize(4); // augmenter la taille dynamiquement
$array[3] = 'souris'; 
foreach ( $array as $value ) 
    echo "[$value],";

Affiche: 
[chien],[chat],[oiseau],[souris] 

De plus, quelques itérateurs ont été ajoutés : FilesystemIterator et GlobIterator. Ils fonctionnent de la même manière que les autres classes d'itérateurs de PHP, mais ils sont conçus pour certaines situations.

Un autre changement avec la SPL est qu'elle est désormais toujours activée depuis PHP 5.3. Dans les versions précédentes, vous pouviez la désactiver au moment de la compilation mais ce n'est plus possible depuis PHP 5.3.

Les nouveautés de la SPL ajoutent des fonctionnalités utiles à PHP, faciles à utiliser, ainsi que des implémentations de structures de données comme les listes doublement liées, les piles, les files et les tas. Ces classes peuvent être utilisées pour remplacer les implémentations « utilisateur » que vous pourriez avoir, ce qui fera gagner de la rapidité à vos scripts et permettra une meilleure intégration avec diverses structures et fonctions PHP.

Maintenant que nous avons vu les ajouts à la SPL, voyons comment la POO a bénéficié d'importantes améliorations en performances et en consommation mémoire dans PHP 5.3 grâce à l'ajout du ramasse miettes (garbage collection) pour les références circulaires.

I-D. Ramasse miettes circulaire

Un problème que les développeurs PHP rencontrent du point de vue des performances, est le ramassage des miettes (garbage collection). PHP a un ramasse miettes assez simple qui s'occupe d'un objet simplement lorsqu'il n'est plus visible. PHP le fait en interne à l'aide d'un compteur de références, de telle manière que lorsque le compteur atteint zéro (c'est-à-dire qu'il n'y a plus aucune référence à l'objet), l'objet est ramassé et la mémoire qui lui était attribuée est libérée.

Cela fonctionne plutôt bien mais cela peut devenir un problème dans les situations où un objet référence un autre objet en relation parent-enfant. Dans cette situation, le compteur de références pour ces objets n'agit pas, ainsi la mémoire utilisée pour ces objets reste dans la mémoire non référencée et elle n'est jamais libérée avant la fin de la requête. Voici un exemple permettant de faire apparaître ce problème :

Listing 11. Relation de classes parent-enfant mal gérée par le ramasse miettes dans PHP 5.2 et antérieurs
Sélectionnez
class LeParent 
{ 
    public function __construct() 
    { 
        $this->child = new Enfant($this); 
    } 
} 

class Enfant 
{ 
    public function __construct(LeParent $parent) 
    { 
        $this->parent = $parent; 
    } 
}

Dans cette situation, chaque fois que vous créez une instance de la classe Parent et que cette instance devient hors de portée, la mémoire n'est pas libérée, ainsi le script continue de consommer davantage de mémoire à mesure qu'il reste en exécution. Il y a quelques solutions possibles en tant qu'utilisateur de PHP, comme créer un destructeur pour la classe parent afin de libérer l'objet enfant. Ce destructeur doit être appelé spécifiquement avant de détruire la référence à la classe parent. Alors que cette méthode fonctionne, elle complique passablement votre code.

Dans PHP 5.3, le ramasse miettes détecte ces références circulaires et il est capable de libérer la mémoire qu'elles utilisent, de façon à ce que la consommation de mémoire par PHP reste linéaire lors de l'exécution du script. Alors que chaque référence à la classe Parent est supprimée, la référence à la classe Enfant à l'intérieur de Parent est également ramassée.

I-E. Conclusion

PHP a fait bien du chemin sur le plan du support de la programmation orientée objet, depuis le faible support ajouté en PHP 4 aux ajouts nettement améliorés dans PHP5 et aux correctifs qui ont suivi. Aujourd'hui, PHP 5.3 a reçu des améliorations intéressantes, notamment des ajouts de syntaxe comme la nouvelle méthode statique __callStatic(), les appels statiques dynamiques, late static binding, les méthodes et les propriétés statiques. Les nouveautés de la SPL avec l'implémentation des listes doublement liées, les piles, les files et les tas mettent à votre disposition des structures de données classiques et simplifient leur utilisation. Enfin, le ramasse miettes circulaire, longuement attendu, résout des problèmes de mémoire et de performances pour les classes auto référencées en implémentant un ramasse miettes nettement amélioré qui libère correctement la mémoire pour ces références circulaires. Toutes ces fonctionnalités font de PHP 5.3 un langage bien plus intéressant pour la programmation orientée objet.


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 John Mertic et Guillaume Rossolini. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.