Singleton pattern in PHP

Citește postarea în română

Share on:

Probably the most popular pattern form PHP and not only.

Motivation:

Restriction to a single instance of a resource across the app, accessible from anywhere.

Diagram:

singleton

Implementation:

The classic example for PHP is the database resource. The database connection must be unique across the app, not to establish multiple connections to the database and as a consequence resources to be wasted.

For a single instance to exist the constructor must only be accessible from a static method, and the resulting object must not have the posibillity to be cloned. Also the class must not be extensible.

Example:

  1// db connection information
  2define ( 'DB_HOST', 'localhost' );
  3define ( 'DB_USER', 'user' );
  4define ( 'DB_PASS', 'pass' );
  5define ( 'DB_DATABASE', 'db' );
  6
  7/**
  8 * Singleton class for database connection management using mysqli
  9 */
 10final class SingletonDB {
 11
 12     /**
 13      * Singleton instance
 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 which also connects to the database
 28      *
 29      */
 30     protected function __construct() {
 31          // connection to database server
 32          $this->_connection = new mysqli ( DB_HOST, DB_USER, DB_PASS );
 33
 34          // in case of an error connection an exception is thrown
 35          if ($this->_connection->connect_error) {
 36               throw new Exception ( 'Error connection to mysql server' );
 37          }
 38
 39          // selecting the database
 40          $this->_connection->select_db ( DB_DATABASE );
 41
 42          // in case of an error selecting the database an exception is thrown
 43          if ($this->_connection->error) {
 44               throw new Exception ( 'Error selecting database' );
 45          }
 46
 47     }
 48
 49     /**
 50      * Run SQL queries
 51      *
 52      * @param string $query SQL query
 53      * @return mysqli_result
 54      */
 55     public function query($query) {
 56          return $this->_connection->query ( $query );
 57     }
 58
 59     /**
 60      * Access for error messages
 61      *
 62      * @return string
 63      */
 64     public function error() {
 65          return $this->_connection->error;
 66     }
 67
 68     /**
 69      * Method that is called when cloning an object
 70      * Is protected so is not possible to clone the object
 71      *
 72      */
 73     protected function __clone() {
 74     }
 75
 76     /**
 77      * Close connection and destroy the object
 78      *
 79      */
 80     public function __destruct() {
 81          $this->_connection->close ();
 82     }
 83
 84     /**
 85      * Method that returns an SingletonDB instance
 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     // SingletonDB instance
100     $db = SingletonDB::getInstance ();
101
102     // Query to be run
103     $q = 'SELECT * FROM test';
104
105     // the query will return an mysqli_result object
106     $result = $db->query ( $q );
107
108     // check for errors and display them
109     if ($db->error ()) {
110
111          echo $db->error ();
112
113     } else {
114          // extract the result and display
115          while ( $row = $result->fetch_assoc () ) {
116               var_dump ( $row );
117          }
118          // close mysqli_result object
119          $result->close ();
120     }
121// in case of exception there is displayed
122} catch ( Exception $e ) {
123     echo $e->getMessage ();
124}