Introduction : Une petite lettre qui change tout
\n\nImaginez : vous développez un super framework PHP ou simplement une bibliothèque pour votre projet. Tout fonctionne parfaitement, mais un mois plus tard, vous remarquez que les classes enfants ne se comportent pas comme prévu. Vous créez un objet, et — boum ! — il retourne une instance de la classe parente. Ça vous parle ? Bienvenue au club de ceux qui ont rencontré new self vs. new static.
\n\nCette question sur Stack Overflow a cumulé des milliers de vues, et pour cause. La différence entre self et static en PHP n'est pas qu'un sucre syntaxique, c'est un mécanisme fondamental qui peut soit sauver votre projet, soit le transformer en cauchemar de maintenance. En 2025, alors que PHP continue d'évoluer, comprendre le late static binding (liaison statique tardive) est devenu une compétence indispensable pour tout développeur qui se respecte.
Dans cet article, nous ne nous contenterons pas de répéter la documentation. Nous analyserons des cas concrets, montrerons des anti-patrons et donnerons des bonnes pratiques claires que vous pourrez appliquer dès aujourd'hui. C'est parti !
\n\nPartie principale : self vs. static — la bataille du contexte
\n\n1. self — le conservateur du compilateur
\n\nLe mot-clé self en PHP fait toujours référence à la classe dans laquelle il est écrit. Considérez-le comme un vieil ami fidèle qui ne change jamais. Lorsque vous écrivez new self() dans une classe parente, ce code créera toujours un objet de cette classe parente — même s'il est appelé par une classe enfant.
<?php\nclass Animal {\n public static function create() {\n return new self(); // Toujours Animal\n }\n}\n\nclass Dog extends Animal {\n // Hérite de create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // Affiche : Animal\n?>\n\nVous voyez ? Nous avons appelé la méthode sur la classe Dog, mais nous obtenons Animal. C'est souvent une surprise pour les débutants. Où est le piège ? Le fait que self est résolu au moment de la compilation. PHP « verrouille » la référence à la classe où la méthode est déclarée, et aucune magie d'héritage ne peut la changer.
2. static — le révolutionnaire de la liaison tardive
\n\nstatic, c'est tout le contraire. Il fonctionne au moment de l'appel de la méthode et détermine quelle classe l'a appelée. C'est ce qu'on appelle le late static binding (liaison statique tardive), introduit en PHP 5.3.0.
<?php\nclass Animal {\n public static function create() {\n return new static(); // Crée une instance de la classe qui a appelé la méthode\n }\n}\n\nclass Dog extends Animal {\n // Hérite de create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // Affiche : Dog\n?>\n\nQuel changement ! Maintenant, Dog::create() retourne un chien, et non un animal abstrait. static regarde qui a appelé la méthode et crée un objet de cette classe. Cela offre une flexibilité incroyable pour construire des hiérarchies de classes.
3. Quand utiliser self et quand utiliser static ?
\n\nRègle d'or : utilisez self lorsque vous avez besoin d'un lien rigide vers la classe actuelle, et static lorsque vous voulez que les classes enfants puissent redéfinir le comportement.
Voici quelques scénarios concrets :
\n\nScénario A : Méthodes de fabrique (Utilisez static)
\nExemple classique : le pattern Factory Method. Vous voulez que chaque classe enfant se crée elle-même.
\n\n<?php\nabstract class Vehicle {\n abstract public function getType(): string;\n\n public static function create(): static {\n return new static();\n }\n}\n\nclass Car extends Vehicle {\n public function getType(): string {\n return 'Voiture';\n }\n}\n\nclass Bike extends Vehicle {\n public function getType(): string {\n return 'Vélo';\n }\n}\n\n$car = Car::create();\necho $car->getType(); // Affiche : Voiture\n$bike = Bike::create();\necho $bike->getType(); // Affiche : Vélo\n?>\n\nScénario B : Singleton et instances uniques (Utilisez self)
\nDans le pattern Singleton, vous voulez garantir une seule instance par classe. self est parfait ici.
<?php\nclass Database {\n private static ?self $instance = null;\n\n public static function getInstance(): self {\n if (self::$instance === null) {\n self::$instance = new self();\n }\n return self::$instance;\n }\n}\n?>\n\nScénario C : Propriétés statiques et constantes (Utilisez self)
\nPour accéder à des propriétés ou constantes statiques qui ne doivent pas être redéfinies, self est le choix sûr.
<?php\nclass Config {\n public const APP_NAME = 'MonApp';\n\n public static function getAppName(): string {\n return self::APP_NAME; // Toujours 'MonApp'\n }\n}\n?>\n\n4. Anti-patrons à éviter en 2025
\n\nMême avec les meilleures intentions, certains pièges sont courants :
\n\n- \n
- Utiliser
selfdans des méthodes destinées à être surchargées : Cela brise la polymorphie et surprend les développeurs. \n - Appeler
new static()dans un constructeur privé : Cela peut causer des erreurs fatales si la classe enfant a un constructeur différent. \n - Mélanger
selfetstaticsans documentation : Votre équipe vous remerciera d'ajouter des commentaires clairs. \n
Conclusion : Devenez un maître du binding
\n\nLa différence entre new self() et new static() est subtile mais cruciale. En 2025, avec des frameworks modernes comme Laravel et Symfony qui exploitent massivement le late static binding, maîtriser ces concepts vous distingue des développeurs moyens.
Rappelez-vous : self est votre allié pour la stabilité, static pour la flexibilité. Choisissez judicieusement, testez vos classes enfants, et votre code PHP sera plus robuste, plus maintenable et plus élégant.
Et vous, quelle est votre expérience avec self et static ? Partagez vos astuces en commentaires !