la derniere goutte

Best practice : Utiliser le singleton

Pourquoi et comment utiliser le singleton en php

singleton php, php singleton, singleton de connexion php, php getinstance, getinstance php, quand utiliser singleton, exemple class en php

Date de publication : 2008-12-15

Le singleton késako ?

Le singleton est un patron de conception (ou design pattern, enfin bref un mot compliqué pour dire une méthode de programmation reconnue par tout le monde), qui limite l'instanciation d'une classe à un objet unique.

Un objet unique dans quel but ? Dans des cas bien précis cela peut être pratique et limiter les erreurs de programmation et les instanciations inutiles d'objets.

Les exemples typiques sont une classe de base de données dans un environnement mono base de données (3/4 des sites internet) ou encore la classe de connexion utilisateur.

Petit exemple avec une classe de connexion utilisateur :
CETTE CLASSE EST LA POUR EXPLIQUER LE CONCEPT DE SINGLETON ET NE PEUT EN AUCUN CAS ÊTRE UTILISER EN PRODUCTION


<?php
class User
{
/**
* true si l'utilisateur est connecté false si non connecté
*
* @var boolean
*/
public $isLogged = false;
/**
* pseudo de l'utilisateur courant
*
* @var string
*/
public $pseudo = '';
private function __construct ()
{
/**On a le cookie l'utilisateur est potentiellement connecté*/
if (isset($_COOKIE['usrId'])) {
$userId = (int) $_COOKIE['usrId'];
/**On récupère l'instance de la base de données (une autre utilisation du singleton :)*/
$db = Database::getInstance();
/**On bind la variable pour protèger des injections SQL*/
$db->bind('USR_ID', $userId);
/**
* On execute la requete
* le paramètre true permet de retourner directement les champs de la table quand il n'y a qu'une seule ligne attendue
*/
$user = $db->select('SELECT USR_PSEUDO FROM USERS WHERE USR_ID=:USR_ID LIMIT', true);
/**Si on a trouver l'utilisateur on récupère son pseudo et on dit qu'il est connecté*/
if (isset($user['USR_PSEUDO'])) {
$this->isLogged = true;
$this->pseudo = $user['USR_PSEUDO'];
}
}
}
/**
* Connecte l'utilisateur courant
*
*/
public function login ()
{
/**On simule la connexion de l'utilisateur 1*/
setcookie('connect', '1', 0, '/');
}
/**
* Vérifie la connexion de l'utilisateur courant
*
*/
public static function checkConnection ()
{
$user = self::getInstance();
if ($user->isLogged === false) {
exit('non connecté');
}
}
/**
* Retourne l'instance de l'utilisateur courant
*
* @return User
*/
public static function getInstance ()
{
static $user;
if (isset($user) === false) {
$user = new User();
}
return $user;
}
}
?>

Utilisation pour connecter l'utilisateur :


<?php
$user = User::getInstance();
$user->login();
?>

Vérifier que l'utilisateur est connecté :


<?php
/**La fonction exit si l'utilsateur n'est pas connecté*/
User::checkConnection();
?>

Afficher le pseudo de l'utilisateur courant :


<?php
$user = User::getInstance();
if ($user->isLogged) {
echo $user->pseudo;
} else {
echo 'non connecté';
}
?>

L'avantage principale de l'utilisation du singleton dans vos scripts php est surtout l'optimisation des performances de vos scripts en évitant les instanciations et donc les traitements inutiles.

Si l'on se trouve sur la page article d'un site on peut supposer que le pseudo de l'utilisateur sera afficher en haut de la page avec la fonction suivante :


<?php
function getLoginBox ()
{
$user = User::getInstance();
echo 'Pseudo :' . $user->pseudo;
}
?>

Et que plus bas dans la page la fonction suivante affichera le formulaire de commentaire :


<?php
function getCommentForm ()
{
$user = User::getInstance();
echo $user->pseudo . ' ajoutez votre commentaire <form>[... reste du code du formulaire]</form>';
}
?>

Si vous n'utilisez pas une forme de singleton dans cette page vous feriez alors deux appels au constructeur de la classe user (en supposant que vous utilisez des objets), ce qui entrainerai deux requêtes en base de données au lieu d'une seule dans la version avec singleton.

Bien sur dans cet exemple c'est flagrant mais je vous assure qu'en utilisant le singleton dans les classes qui s'y prêtent vous remercierai ce design pattern de vous éviter des tas de traitements inutiles.

Voilà je vous quitte en espérant que je croiserai de plus en plus de singleton :D.

Image : muha

 
 

b1n@sp1n