6.Le langage PHP

6.8.Programmation orientée objet

6.8.5.Les espaces de nom

6.8.5.1.Introduction

Dans les paragraphes précédents nous avons vu comment instancier des objets, appeler des méthodes, faire référence à des variables membres et constantes de classe[où?], nous avons appris à gérer des exceptions[où?] puis nous avons vu comment implémenter nos propres classes et interface[où?] mais nous avons passé sous silence, un aspect important de la programmation objet (et d'autres domaines): l'espace de nom.
Si vous souhaitez créer une application un peu complexe, vous aurez à faire appel à des bibliothèques de classes provenant pourquoi pas de sources différentes. Et il est important que l'ensemble de ces bibliothèques puissent cohabiter ensemble. Je veux dire par là, qu'il ne faut pas qu'une bibliothèque empêche votre programme ou une autre bibliothèque de fonctionner, ce qui pourrait arriver si chacun crée dans son coin des classes portant le même nom (mais ne faisant évidemment pas exactement la même chose). Pour éviter les risques de collision entre les noms de classes, celles-ci sont placé dans un context, un espace de nom qui pourra être clairement identifié (en tenant compte par exemple, du nom de l'organisation à l'origine du code, du nom de la bibliothèque, etc.).
En bref:
<?php
namespace PHPFacile\Tuto;

use Biblio\UneClasse;
use Biblio\MaClasseAMoi as SaClasseALui;

class MaClasseAMoi
{
    public function maMethode()
    {
        $objet = new MonAutreClasse(); // Fait référence à \PHPFacile\Tuto\MonAutreClasse;
        $objet = new PHP\MaClasse(); // Fait référence à \PHPFacile\Tuto\PHP\MaClasse;

        $objet = new UneClasse(); // Fait référence à \Biblio\UneClasse;
        $objet = new SaClasseALui(); // Fait référence à \Biblio\MaClasseAMoi;

        $objet = new \CheminComplet\AutreClasse();
    }
}

6.8.5.2.Déclaration de l'espace de nom de la classe

Comme nous l'avons vu, il est recommandé, d'isoler le code d'une classe donnée dans un fichier dédié. Pour lui associer un espace de nom, il suffit de commencer le fichier par le mot clé namespace suivi de l'espace de nom qui est une chaîne de caractères représentant un chemin (à l'image du chemin d'un fichier dans une arborescene) qui peut être défini librement avec pour séparateur le caractère '\' (anti-slash).
<?php
namespace PHPFacile\Tuto;

class MaClasseAMoi
{
    // Corps de la classe
}
Le nom complet de la classe est alors l'espace de nom + le nom tel qu'on le trouve après le mot clé class (avec entre deux, le délimiteur '\'). Donc ici, PHPFacile\Tuto\MaClasseAMoi ou plus exactement \PHPFacile\Tuto\MaClasseAMoi (avec un anti-slash en tout début. Nous verrons ce qui se cache derrière cette remarque, par la suite).
On fait donc référence à la classe et a ses méthodes de la façon suivante:
<?php
$objet = new \PHPFacile\Tuto\MaClasseAMoi(); // Pour une instanciation
$objet->nomMethode();
\PHPFacile\Tuto\MaClasseAMoi::nomMethode(); // Pour un appel statique
if ($objet instanceof \PHPFacile\Tuto\MaClasseAMoi) {
    echo '$objet est de type \PHPFacile\Tuto\MaClasseAMoi';
}

6.8.5.3.Utilisation des espaces de nom

6.8.5.3.1.Déclaration des classes avec "use"

Comme vous pouvez le constater l'utilisation des espaces de nom peut conduire à alourdir considérablement le code mais heureusement l'exemple présenté dans le paragraphe précédent n'est pas totalement représentatif (même s'il peut arriver d'utiliser ce type d'écriture).
Si l'on ne souhaite pas préciser l'espace de nom à chaque fois que l'on fait référence à un objet appartenant à un espace de nom donné, il suffit d'indiquer (typiquement en début de script) le nom complet (avec l'espace de nom) de la classe utilisée et par la suite seul le nom "court" de la classe sera nécessaire. Pour cela, il faut utiliser le mot clé use suivi du nom complet de la classe (avec autant de ligne "use" que de classes à utiliser de la sorte). L'exemple précédent est donc équivalent à
<?php
use PHPFacile\Tuto\MaClasseAMoi;

$objet = new MaClasseAMoi(); // Pour une instanciation
$objet->nomMethode();
MaClasseAMoi::nomMethode(); // Pour un appel statique
if ($objet instanceof MaClasseAMoi) {
    echo '$objet est de type \PHPFacile\Tuto\MaClasseAMoi';
}

6.8.5.3.2.Déclaration d'alias avec "as"

Si l'utilisation d'un espace de nom simplifie l'écriture, il renvoit néanmoins au problème initial, comment distinguer deux classes portant le même nom? Si au sein d'un même script je souhaite déclarer "use PHPFacile\Tuto\MaClasseAMoi;" et "use BibliothequeAutre\MaClasseAMoi" comment savoir par la suite à quelle "MaClasseAMoi" je fais référence?. C'est impossible en l'état et d'ailleurs l'interpréteur de commande retournera une erreur "PHP Fatal error: Cannot use xxx as yyy because the name is already in use in ...". Alors, il est certes possible d'utiliser les noms complets mais une autre option se présente à nous: utiliser le mot clé as afin de modifier le nom sous lequel la classe sera identifiée dans le script PHP.
<?php
use PHPFacile\Tuto\MaClasseAMoi;
use BibliothequeAutre\MaClasseAMoi as ClasseDeLaBibliotheque;

// ClasseDeLaBibliotheque fait référence à \BibliothequeAutre\MaClasseAMoi
// tandis que MaClasseAMoi fait référence à \PHPFacile\Tuto\MaClasseAMoi

6.8.5.3.3.Espace de nom au sein d'une classe

Au sein d'une classe, par défaut (en l'absence de l'utilisation du mot clé "use" et tant que des chemins complets ne sont pas précisés) les classes appelées sont supposées être celles de l'espace de nom de la classe en question.
<?php
namespace PHPFacile\Tuto;

use Biblio\ClasseDeLaBibliotheque;

class MaClasseAMoi
{
    public function maMethode()
    {
        $objet = new MonAutreClasse(); // Fait référence à \PHPFacile\Tuto\MonAutreClasse;
        $objet = new ClasseDeLaBibliotheque(); // Fait référence à \Biblio\ClasseDeLaBibliotheque;
        $objet = new \CheminComplet\AutreClasse();

        // Les espaces de nom se comportent comme des chemins (fichier)
        $objet = new PHP\MaClasse(); // Fait référence à \PHPFacile\Tuto\PHP\MaClasse;
    }
}
warning
  • Il est facile de se faire avoir. Si vous souhaitez faire appel à une classe native de PHP (ex: DateTime ou Exception) au sein d'une classe avec son espace de nom propre, n'oubliez pas de préciser le nom complet à savoir: \DateTime ou \Exception ou bien d'inclure les lignes "use DateTime;" et "use Exception;".
  • Cette remarque vaut au moment de l'instanciation mais aussi par exemple dans les blocs try ... catch ou encore dans les évaluations "instanceof".
<?php
namespace PHPFacile\Tuto;

class MaClasseAMoi
{
    public function maMethode($str)
    {
        try {
            $dateTime = new \DateTime($str);
        } catch (\Exception $e) {
            // Exception à traiter
        }
    }
}
ou
<?php
namespace PHPFacile\Tuto;

use DateTime;
use Exception;

class MaClasseAMoi
{
    public function maMethode($str)
    {
        try {
            $dateTime = new DateTime($str);
        } catch (Exception $e) {
            // Exception à traiter
        }
    }
}
Ici vous pouvez apprendre :
Forum PHP
Version imprimable: imprimer