New self vs new static en PHP : que choisir en 2025 ?
Imaginez : vous programmez en PHP depuis plusieurs années, vous vous sentez confiant, et soudain votre collègue (ou Stack Overflow) vous pose une question : « Pourquoi dans ma classe enfant un objet de la classe parente est créé, alors que j’appelle le constructeur via new self() ? ». Cela vous parle ? Si oui, vous n’êtes pas seul. Le sujet new self vs new static est l’une des questions les plus populaires sur Stack Overflow avec des milliers de vues. Et en 2025, avec la sortie des nouvelles versions de PHP, comprendre cette différence est devenu encore plus important.
Dans cet article, nous allons voir en quoi self et static diffèrent lors de la création d’objets, comment fonctionne la liaison statique tardive (Late Static Binding) et, surtout, quand utiliser quoi. C’est parti !
Le problème : self pointe toujours vers le parent
Commençons par un exemple classique. Supposons que nous ayons une classe parente BaseController et une classe enfant ApiController.
<?php
class BaseController { public static function create() { return new self(); // Attention ! self est BaseController }}
class ApiController extends BaseController { // Hérite de create()}
$api = ApiController::create();var_dump($api); // object(BaseController)#1 (0) { }?>Nous nous attendions à obtenir un objet ApiController, mais nous avons obtenu BaseController. Pourquoi ? Parce que self dans le contexte de la classe parente fait toujours référence à la classe où il est écrit, et non à la classe par laquelle il a été appelé. C’est ce qu’on appelle la liaison statique précoce. PHP « mémorise » la classe lors de la compilation, et non lors de l’exécution.
Solution : utiliser static
Pour corriger la situation, il faut remplacer self par static. Cela active le mécanisme de liaison statique tardive (LSP).
<?php
class BaseController { public static function create() { return new static(); // static est la classe qui a appelé la méthode }}
class ApiController extends BaseController { // Hérite de create()}
$api = ApiController::create();var_dump($api); // object(ApiController)#1 (0) { }?>Maintenant, $api est un objet ApiController. static est résolu lors de l’exécution et pointe vers la classe par laquelle la méthode a été appelée. C’est cela, la liaison statique tardive.
Quand utiliser self et quand utiliser static ?
En 2025, les meilleures pratiques distinguent clairement ces deux approches. Voici les règles principales.
Utilisez self lorsque :
- Vous travaillez à l’intérieur d’une seule classe et n’attendez pas d’héritage pour cette méthode.
- Vous devez créer un objet de la classe exacte dans laquelle le code est écrit, et non d’une classe enfant.
- Vous accédez à des constantes ou des propriétés statiques qui ne doivent pas être redéfinies.
Exemple : une méthode de fabrique qui retourne de manière garantie un objet de la classe de base.
<?php
class Logger { protected static $instance;
public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); // Toujours Logger } return self::$instance; }}?>Utilisez static lorsque :
- Vous concevez du code pour l’extension — par exemple, des classes abstraites ou des traits.
- Vous avez besoin que les classes enfants puissent créer leurs propres instances.
- Vous utilisez le pattern Factory Method ou Builder.
Exemple : une classe abstraite pour les entités.
<?php
abstract class Entity { public static function create(array $data): static {\