Singleton pattern in PHP

Read this post in English

Share on:

Probabil cel mai cunoscut pattern de PHP si nu numai.

Motivatie:

Restrictionarea la o singura instanta a unei resurse in toata aplicatia, accesibila de oriunde.

Diagrama:

singleton

Implementare:

Exemplul clasic pentru PHP este resursa de conectare la baze de date. Conexiunea la baza de date trebuie sa fie unica in toata aplicatia pentru a nu stabili conexiuni multiple la baza de date si in consecinta sa fie consumate resurse inutil.

Pentru ca sa existe o singura instanta constructorul nu trebuie sa fie accesibil decat printr-o metoda statica, iar obiectul rezultatul nu trebuie sa aiba posibilitatea de clonare. De asemenea clasa nu trebuie sa aiba posibilitatea de a fi extinsa.

Exemplu:

  1// date conectare db
  2define ( 'DB_HOST', 'localhost' );
  3define ( 'DB_USER', 'user' );
  4define ( 'DB_PASS', 'pass' );
  5define ( 'DB_DATABASE', 'db' );
  6
  7/**
  8 * Clasa singleton pentru managementul conexiunii la baza de date folosind mysqli
  9 */
 10final class SingletonDB {
 11
 12     /**
 13      * Instanta singleton
 14      *
 15      * @var SingletonDB
 16      */
 17     protected static $_instance = null;
 18
 19     /**
 20      * Connection resource
 21      *
 22      * @var resource
 23      */
 24     protected $_connection = null;
 25
 26     /**
 27      * Constructor care realizeaza si conexiunea la baza de date
 28      *
 29      */
 30     protected function __construct() {
 31          // conectare server baze de date
 32          $this->_connection = new mysqli ( DB_HOST, DB_USER, DB_PASS );
 33
 34          // in cazul in care conexiunea este nereusita se trimite o exceptie
 35          if ($this->_connection->connect_error) {
 36               throw new Exception ( 'Error connection to mysql server' );
 37          }
 38
 39          // selectare baza de date
 40          $this->_connection->select_db ( DB_DATABASE );
 41
 42          // in cazul in care selectarea este nereusita se trimite o exceptie
 43          if ($this->_connection->error) {
 44               throw new Exception ( 'Error selecting database' );
 45          }
 46
 47     }
 48
 49     /**
 50      * Rulare interogare SQL
 51      *
 52      * @param string $query Interogare SQL
 53      * @return mysqli_result
 54      */
 55     public function query($query) {
 56          return $this->_connection->query ( $query );
 57     }
 58
 59     /**
 60      * Acces mesaj eroare
 61      *
 62      * @return string
 63      */
 64     public function error() {
 65          return $this->_connection->error;
 66     }
 67
 68     /**
 69      * Metoda care se apeleaza la clonare
 70      * Este protected pentru ca obiectul nu trebuie clonat
 71      *
 72      */
 73     protected function __clone() {
 74     }
 75
 76     /**
 77      * Intrerupe conexiunea
 78      *
 79      */
 80     public function __destruct() {
 81          $this->_connection->close ();
 82     }
 83
 84     /**
 85      * Metoda care va intoarce instanta singleton
 86      *
 87      * @return SingletonDB
 88      */
 89     public static function getInstance() {
 90          if (self::$_instance == null) {
 91               self::$_instance = new SingletonDB ( );
 92          }
 93
 94          return self::$_instance;
 95     }
 96}
 97
 98try {
 99     // Instanta SingletonDB
100     $db = SingletonDB::getInstance ();
101
102     // Interogare de executat
103     $q = 'SELECT * FROM test';
104
105     // interogarea va returna un obiectu mysqli_result
106     $result = $db->query ( $q );
107
108     // Se verifica daca exista erori si se afisaza
109     if ($db->error ()) {
110
111          echo $db->error ();
112
113     } else {
114          // se extrag rezultatele si se afisaza pe ecran
115          while ( $row = $result->fetch_assoc () ) {
116               var_dump ( $row );
117          }
118          // se inchide obiectul de mysqli_result
119          $result->close ();
120     }
121// in cazul in care apar exceptii acestea se afisaza
122} catch ( Exception $e ) {
123     echo $e->getMessage ();
124}