W3docs

insteadof

Le mot-clé "insteadof" en PHP permet de spécifier quel trait utiliser à la place d'un autre lors d'un conflit de méthode.

Le mot-clé PHP insteadof

insteadof est un mot-clé PHP utilisé à l'intérieur d'un bloc use pour résoudre un conflit de méthode entre deux traits ou plus. Lorsqu'une classe utilise plusieurs traits qui définissent chacun une méthode portant le même nom, PHP ne peut pas décider lequel prend la priorité et déclenche une erreur fatale. insteadof indique à PHP quelle méthode de trait conserver et laquelle ignorer.

Cette page explique le conflit qu'il résout, sa syntaxe exacte, comment il s'associe au mot-clé as pour conserver la méthode « perdante », ainsi que les pièges à connaître.

Le problème que insteadof résout

Un trait est un bloc réutilisable de méthodes qui est copié dans une classe au moment de la compilation. Si deux traits définissent une méthode portant le même nom et qu'une classe utilise les deux, PHP ne peut pas en choisir une. Le résultat est une erreur fatale de collision :

<?php

trait FileLogger {
  function log() { echo "Writing to a file."; }
}
trait DatabaseLogger {
  function log() { echo "Writing to the database."; }
}

class Service {
  use FileLogger, DatabaseLogger; // No conflict resolution
}

// PHP Fatal error: Trait method DatabaseLogger::log has not been
// applied as Service::log, because of collision with FileLogger::log

La classe n'est même jamais créée — il s'agit d'une erreur à la compilation, pas à l'exécution. insteadof est la façon d'indiquer à PHP quelle méthode appliquer.

Syntaxe

insteadof s'écrit à l'intérieur du bloc entre accolades d'une instruction use :

use TraitWeKeep, TraitWeDrop {
    TraitWeKeep::methodName insteadof TraitWeDrop;
}

Lisez-le comme : « utiliser la méthode methodName de TraitWeKeep à la place de celle de TraitWeDrop. » Le trait nommé après insteadof voit sa version de cette méthode supprimée de la classe.

<?php

trait FileLogger {
  function log() { echo "Writing to a file."; }
}
trait DatabaseLogger {
  function log() { echo "Writing to the database."; }
}

class Service {
  use FileLogger, DatabaseLogger {
    FileLogger::log insteadof DatabaseLogger;
  }
}

$service = new Service();
$service->log();
// Output: Writing to a file.

Résolution contre plus d'un trait

Si trois traits ou plus entrent en collision, listez tous les traits à exclure après insteadof, séparés par des virgules :

<?php

trait Json    { function format() { echo "JSON output"; } }
trait Xml      { function format() { echo "XML output"; } }
trait Csv      { function format() { echo "CSV output"; } }

class Report {
  use Json, Xml, Csv {
    Json::format insteadof Xml, Csv;
  }
}

$report = new Report();
$report->format();
// Output: JSON output

Conserver l'autre méthode avec as

insteadof supprime une méthode — mais souvent vous ne voulez pas la perdre, vous souhaitez simplement la nommer différemment pour que les deux soient disponibles. C'est ce que fait le mot-clé as : il crée un alias de la méthode exclue sous un nouveau nom afin qu'elle survive à la résolution du conflit.

<?php

trait FileLogger {
  function log($msg) { return "[file] $msg"; }
}
trait DatabaseLogger {
  function log($msg) { return "[db] $msg"; }
}

class Service {
  use FileLogger, DatabaseLogger {
    FileLogger::log insteadof DatabaseLogger;  // FileLogger::log becomes log()
    DatabaseLogger::log as logToDb;            // DatabaseLogger::log survives as logToDb()
  }
}

$service = new Service();
echo $service->log("started"), "\n";      // [file] started
echo $service->logToDb("started"), "\n";  // [db] started

insteadof et as sont presque toujours utilisés ensemble : insteadof désigne le vainqueur, as sauve le perdant sous un alias. Le mot-clé as peut également modifier la visibilité d'une méthode (par exemple FileLogger::log as protected;).

Pièges à éviter

  • insteadof résout uniquement les conflits de nom. Si les deux méthodes n'ont pas le même nom, il n'y a pas de conflit et insteadof est inutile.
  • Vous devez référencer une méthode qui existe réellement dans le trait nommé, en utilisant la syntaxe Trait::method. Une faute de frappe produit une erreur fatale.
  • Il ne fusionne pas les comportements. La méthode exclue n'est simplement pas appliquée ; insteadof n'appelle jamais les deux méthodes.
  • Une classe enfant l'emporte toujours sur un trait. L'ordre de résolution des méthodes est le suivant : les méthodes définies dans la classe elle-même écrasent les méthodes des traits, et les méthodes des traits écrasent les méthodes héritées (de la classe parente).

Quand l'utiliser

Utilisez insteadof chaque fois que vous composez une classe à partir de plusieurs traits et que deux d'entre eux exposent le même nom de méthode — ce qui est courant lorsque vous mélangez des traits tiers que vous ne contrôlez pas. Combiné avec as, il vous permet de composer des comportements à partir de traits indépendants sans renommer leur code source, ce qui maintient vos classes modulaires et sans conflit.

Pratique

Pratique
Que fait le mot-clé 'insteadof' en PHP ?
Que fait le mot-clé 'insteadof' en PHP ?
Was this page helpful?