Comme vous le voyez on commence à vouloir se créer une classe pour un petit peu tout. Mais ne risque-t-on pas d'avoir des collisions ? 2 classes ne peuvent effectivement pas avoir le même nom, du coup il a fallu imaginer une solution à ce problème : Les namespaces.

Pour éviter les collisions dans les différentes classes on avait pris l'habitude de préfixer les noms des classes comme par exemple Zend Zend_Gdata_YouTube. Le problème de cette méthode c'est que les noms de classe deviennent vite abominable et qu'il peut être rapidement pénible de les répéter dans notre code.

Les namespaces permettent de définir un nom de package que l'on pourra ensuite charger de manière automatique gràce à un autoloading. Par exemple, nous allons placer notre class Form dans un namespace HTML.

namespace Tutoriel\HTML;
class Form {
    // ...
}

On prendra l'habitude de créer nos classes dans un namespace pour éviter les collisions (ici j'ai choisi Tutoriel). Ma classe form est maintenant appellable en faisant

new \Tutoriel\Html\Form(); 

On est tenté de se dire que les namespace ne permettent aucun avantage par rapport à la méthode précédente car au final les noms de classes sont tout aussi long qu'avant... Heureusement il est possible de préciser au début de notre fichier les classes que nous allons utiliser pour les charger automatiquement

use \Tutoriel\Html\Form ;
new Form(); 

La notation peut sembler perturbante quand on début mais il faut imaginer ça comme des dossiers

  • namespace, permet de dire "je travaille dans ce dossier"
  • use, permet d'importer une class d'un autre "dossier"

Je pense que cette analogie est importante pour comprendre le fonctionnement des namespaces. Si on souhaite charger une classe de PHP (par exemple DateTime) après avoir déclaré un namespace il faudra alors préfixer par un \

namespace Tutoriel;
// \ devant permet de revenir à la racine
new \DateTime();
new \PDO();
new HTML\Form(); // équivaut à \Tutoriel\HTML\Form(); car on est déjà dans Tutoriel

Enfin nous devront modifier notre autoloader pour ne charger que les classes de ce namespace et prendre en compte la nouvelle architecture

<?php
namespace Tutoriel;
/**
 * Class Autoloader
 * @package Tutoriel
 */
class Autoloader{

    /**
     * Enregistre notre autoloader
     */
    static function register(){
        spl_autoload_register(array(__CLASS__, 'autoload'));
    }

    /**
     * Inclue le fichier correspondant à notre classe
     * @param $class string Le nom de la classe à charger
     */
    static function autoload($class){
        if (strpos($class, __NAMESPACE__ . '\\') === 0){
            $class = str_replace(__NAMESPACE__ . '\\', '', $class);
            $class = str_replace('\\', '/', $class);
            require 'class/' . $class . '.php';
        }
    }

}