Archives de catégorie : Développement web

Les singletons : design pattern

Un singleton est un design pattern dont l’objet consiste à avoir une classe qui ne peut être instanciée qu’une seule fois.

Ce serait le cas typique de la configuration d’un site web. Il serait absurde de créer plusieurs objets configuration s’agissant d’un seul et même site web.

A chaque instanciation de Config, on ferait par exemple:

1
2
3
4
5
$config1 = new Config();

...

$config2 = new Config();

Un nouvel objet Config est créé à chaque fois. Ce qui nous arrange pas vraiment.

Une solution à ce problème serait de de créer une classe statique. Celle-ci n’ayant pas besoin d’être instanciée. Il s’avère cependant que ces classe statiques ne peuvent pas disposer de constructeur, de plus gérer l’héritage des classes statiques est assez complexe. (voir Late Static Bindings).

La solution consiste donc à créer une nouvelle instance de la classe seulement si aucune instance de cette classe n’a déjà été créée.

Supposons que notre classe Config soit chargée de gérer la configuration de notre application qui se trouve dans un fichier config/config.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

class Config {
  private $settings = [];
  private static $_instance;

  public static function getInstance(){
    if(is_null(self::$_instance)){
      self::$_instance = new Config();
    }
    return self::$_instance;
  }

  public function __construct(){
    $this->settings = require dirnam(__DIR__) . 'config/config.php';
  }
}

C’est donc dans la méthode :

1
2
3
4
5
6
public static function getInstance(){
    if(is_null(self::$_instance)){
      self::$_instance = new Config();
    }
    return self::$_instance;
  }

que l’instance de Config est créée. On voit bien ici, que Config n’est instancié que s’il n’existe pas encore d’objet.

A chaque endroit où j’ai besoin de ma configuration, je l’appelle de cette manière

1
$config = Config::getInstance();

De cette façon, l’objet Config n’est créé que s’il n’a pas déjà été préalablement instancié .

L’autoloading dans PHP

L’autoloading permet de charger automatiquement les classes.

Au lieu d’ajouter un

1
require 'className.php';

à chaque fois que l’on a besoin d’une classe, on va créer un autoloader qui charge automatiquement les classes.

Pour créer un autoloader qui charge les classes à chaque fois qu’il rencontre une directive new comme dans :

1
new className();

nous devons d’abord créer la fonction:

1
2
3
function __autolad($class_name){
   require 'class/' . $class_name . '.php';
}

dès à présent nous n’avons plus besoin d’utiliser de

1
require 'className.php';

C’est l’autoloader qui s’en charge maintenant d’inclure la déclaration de la classe.

L’inconvénient ici, c’est que toutes les classes doivent se trouver dans le dossier class/ et il n’est pas possible de déclarer d’autre autoloaders

La solution pour remédier à ce problème consiste ici à déclarer l’autoloader de cette manière

1
2
3
function myAutoloader($class_name){
   require 'class/' . $class_name . '.php';
}

et d’utiliser la fonction

1
spl_autoloader_register('myAutoloader');

qui enregistre la fonction myAutoloader() dans la pile __autoload()

Nous pourront ainsi déclarer plusieurs autoloaders

Une idée encore meilleure ici est de créer une classe Autoloader

1
2
3
4
5
6
7
8
class Autoloader {
 static function register(){
  spl_autoload_register(array(__CLASS__,'autoload'));
 }
 static function autoload($class_name){
  require 'class/' . $class_name . '.php';
 }
}

Il faudra ensuite inclure uniquement la classe Autoloader et appeler notre méthode register de Autoloader

1
2
require 'class/autoloader.php';
Autoloader::register();

avant d’instancier nos classes.

De cette manière, il ne sera plus nécessaire d’inclure les déclarations de classes et il sera possible d’inclure d’autres autoloaders.