J'ai donc été très surpris lorsque Dmitry Stogov a fermé mon rapport de bug en me disant que ce n'était pas un bug, mais une fonctionnalité.

Connaissant un peu Dmitry, je me suis permis de lui demander des détails supplémentaires par courrier électronique, car je ne comprenais pas son explication.

Et quelques temps plus tard, j'ai reçu une réponse détaillée et très pédagogique, qui m'a permis de comprendre le problème.

J'ai donc décidé de vous en faire profiter, car à l'époque, le problème, que j'avais exposé sur twitter, avait suscité l'attention de certains.

En résumé, il n'est pas possible d'importer, par exemple, une classe dans un fichier sous le nom foo si une classe portant le nom foo est déjà définie au moment de l'importation.

Cela semble évident, mais dans mon cas, j'avais quelques difficultés à visualisé l'ordre dans lequel mes classes étaient définies.

Trés patient et pédagogue, Dmitry m'a alors commenté mon code afin que je comprenne ce qu'il se passait au niveau du Zend Engine lorsqu'il était exécuté :

require_once 'ns_class2.php';
// <-- nouvelle portée de fichier
namespace ns; // Déclaration de l'espace de nom "ns"
class class2 {} // Déclaration de la classe "ns/class2"
// Dans l'espace de noms "ns", "class2" est un alias de "ns\class2"
// Fin de la portée de fichier -->
require_once 'ns_ns1_ns2_class2.php';
// <-- nouvelle portée de fichier
namespace ns\ns1\ns2; // Déclaration de l'espace de nom "ns\ns1\ns2"
class class2 {} // Déclaration de la classe "ns\ns1\ns2\class2"
// Dans l'espace de noms "ns\ns1\ns2", "class2" est un alias de "ns\ns1\ns2\class2"
// Fin de la portée de fichier -->
require_once 'ns_ns1_ns2_class1.php';
// <-- nouvelle portée de fichier
namespace ns\ns1\ns2; // Déclaration de l'espace de nom "ns\ns1\ns2"
// Dans l'espace de noms "ns\ns1\ns2", "class2" est un alias de "ns\ns1\ns2\class2"
use ns\class2; // Création de l'alias "class2" qui pointe vers "ns\class2" mais class2 est déjà un alias de ns\ns1\ns2\class2 => ERREUR !

En résumé, l'ordre dans lequel sont inclus les classes est important dans ce contexte, et il faut donc éviter d'importer des classes en utilisant des noms qui sont susceptibles d'avoir été déclarés avant l'importation, quitte à utiliser le mécanisme d'alias via le mot-clef as pour éviter les collisions éventuelles.

Une autre solution peut être d'importer uniquement des espaces de noms, et non des classes, mais il faut dans ce cas être certain qu'aucune classe ne portera un jour le nom d'un espace de noms.