Page 1 sur 1

[POO] [PHP5] Design Pattern Singleton pour connexion base de

Posté : 04 juil. 2008, 14:02
par nightkid83
Bonjour tout le monde, voila je suis débutant dans la POO et je viens de créer une classe qui me permet de me connecter a une base de données en utilisant PDO, le prob est que j'ai voulu utilisé le motif de conception "Singleton" mais je ne sais pas trop si ce que j'ai fait est juste ou pas. J'aimerai avoir votre avis ainsi que vos suggestions afin d'améliorer ma Classe, merci d'avance.

voici la Classe en question
<?php
 
class DatabaseConnection
{
    private static $_instance = null;
 
    private $_host;
    private $_user;
    private $_password;
    private $_dbname;
    private $_handle;
 
    private function __construct($dbname = 'nightkid')
    {
        $this->_host     = 'localhost';
        $this->_user     = 'root';
        $this->_password = '';
        $this->_dbname   = $dbname;
        $this->_handle   = null;
        
        try {
            $this->_handle = new PDO("mysql:host=$this->_host;dbname=$this->_dbname", $this->_user, $this->_password);
            $this->_handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            echo 'Connection established and database "' . $this->_dbname . '" selected.';
        } catch (PDOException $e) {
            die('Connection failed or database cannot be selected : ' . $e->getMessage());
        }
    }
 
    public function __destruct()
    {
        var_dump($this->_db); // Vérification
        if (!is_null($this->_handle)) {
            $this->_handle = null;
            echo 'Connection closed.';
        }
        var_dump($this->_db); // Une dernière vérification pour voir si l'objet a été détruit
    }
 
    public static function getInstance()
    {
        if (is_null(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
 
    public function handle()
    {
        return $this->_handle;
    }
}
Maintenant, par exemple, j'utilise cette Classe comme suit :
<?php
 
require_once 'DatabaseConnection.php';
 
class Albums
{
    private $_db;
    private $_sql;
    private $_statement;
 
    public function __construct()
    {
        $this->_db = DatabaseConnection::getInstance()->handle();
    }
 
    public function __destruct()
    {
        var_dump($this->_db); // Vérification
    }
 
    public function addAlbum($artist, $title)
    {
        try {
            $this->_sql = "INSERT INTO albums (artist, title) VALUES (:artist, :title)";
            $this->_statement = $this->_db->prepare($this->_sql);
            $this->_statement->bindParam(':artist', $artist);
            $this->_statement->bindParam(':title', $title);
            $this->_statement->execute();
            echo 'Album added.';
        } catch (PDOException $e) {
            die('Error->addAlbum() : ' . $e->getMessage());
        }
    }
 
    public function editAlbum($id, $artist, $title)
    {
        try {
            $this->_sql = "UPDATE albums SET artist = :artist, title = :title WHERE id = :id";
            $this->_statement = $this->_db->prepare($this->_sql);
            $this->_statement->bindParam(':id', $id);
            $this->_statement->bindParam(':artist', $artist);
            $this->_statement->bindParam(':title', $title);
            $this->_statement->execute();
            echo 'Album information updated.';
        } catch (PDOException $e) {
            die('Error->editAlbum() : ' . $e->getMessage());
        }
    }
 
    public function deleteAlbum($id)
    {
        try {
            $this->_sql = "DELETE FROM albums WHERE id = :id";
            $this->_statement = $this->_db->prepare($this->_sql);
            $this->_statement->bindParam(':id', $id);
            $this->_statement->execute();
            echo 'Album deleted.';
        } catch (PDOException $e) {
            die('Error->deleteAlbum() : ' . $e->getMessage());
        }
    }
 
    public function selectAlbum($id = null)
    {
        try {
            if ($id !== null && $id > 0) {
                $this->_sql = "SELECT id, artist, title FROM albums WHERE id = :id";
                $this->_statement = $this->_db->prepare($this->_sql);
                $this->_statement->bindParam(':id', $id);
            } else {
                $this->_sql = "SELECT id, artist, title FROM albums";
                $this->_statement = $this->_db->prepare($this->_sql);
            }
            $this->_statement->setFetchMode(PDO::FETCH_ASSOC);
            $this->_statement->execute();
            return $this->_statement->fetchAll();
        } catch (PDOException $e) {
            die('Error->selectAlbum() : ' . $e->getMessage());
        }
    }
}
PS: J'aimerai aussi savoir si l'utilisation de la méthode magique "__destruct" dans la Classe "DatabaseConnection" est utile dans ce cas là ou pas.

Posté : 04 juil. 2008, 14:29
par savageman
Salut,

Quelques remarques en vrac :
1) Tu n'utilises pas l'agument de ton constructeur.
2) Ton code serait plus simple si tu faisais hériter ta classe directement de la classe PDO (tu pourrais supprimer la variable $_handle).

Le principe est là sinon.

@+

Posté : 04 juil. 2008, 23:45
par Hywan
Hey :),

Tu as bien compris le principe du Singleton, et le code est bon. Je n'ai rien à ajouter quant à ce qu'a dit savageman.

Pour répondre à ta question sur le __destruct, il ne te sert à rien pour ce que tu fais dedans. Si tu n'utilises plus l'objet, il sera automatiquement détruit. Et de toute façon, avec PHP 5.3, on aura un garbage collector, alors là, la panacée ;-).

La méthode __destruct est lancée avant de détruit l'objet. Donc elle peut fermer des connexions, mais en général, PHP le gère, donc autant le laisser faire.
C'est utile si tu veux écrire des logs ou des choses du genre. Dans ton cas, il n'y a pas grand intérêt.

Posté : 20 août 2008, 20:03
par Julien Breux
J'ajouterai un petit plus en rapport avec le singleton qui est, rappelons-le, le plus simple des design patterns ;)

N'oublie pas d'ajouter l'anti cloning (petit non perso)
 public function __clone()
{
  throw new Exception('Je suis un singleton, ne me clonez pas !');
}

Posté : 01 sept. 2008, 18:02
par doctorrock
Un autre anti cloning sympa :
private function __clone()
{
}

Posté : 01 sept. 2008, 18:08
par Julien Breux
Un autre anti cloning sympa :
private function __clone()
{
}
Je trouve en effet le tient beaucoup plus simple. :oops:

Posté : 27 nov. 2008, 02:09
par simoh
Un autre anti cloning sympa :
private function __clone()
{
}
Je trouve en effet le tient beaucoup plus simple. :oops:
Pourriez-vous me dire à quoi sert le mot-clé __clone
merci d'avance