Blog Reacción Estudio

¡Tu zona de aprendizaje!

Clase para conectar a una base de datos MySQL con PHP usando Singleton

Singleton es un patrón de diseño utilizado para que una clase tenga una única instancia en toda la aplicación y se pueda acceder a ella de forma global.

No siempre es necesario usar el patrón Singleton en nuestras clases, pero es realmente útil a la hora de hacer consultas a la base de datos.

Si nos conectamos a nuestra base de datos de la forma tradicional con PHP, es decir, usando la función «mysqli_connect«, estaremos creando una nueva conexión a la base de datos cada vez que ejecutemos esta función.

Sin embargo, si utilizamos Singleton para conectarnos a nuestra base de datos, nos conectaremos una única vez, por lo que cuando queramos ejecutar una consulta recuperaremos la instancia de nuestra clase que contiene la primera y única conexión hacia nuestra base de datos, obteniendo un menor consumo de recursos por parte de nuestro servidor web.

Una vez explicado que es el Singleton, vamos a ver cómo sería una clase utilizando este patrón para conectarnos a nuestra base de datos MySQL utilizando PHP 5.

    class Database
    {        
        private $_connection;
        private static $_instance; //The single instance
        private $_host = "localhost";
        private $_username = "db_user";
        private $_password = "db_password";
        private $_database = "db_name";

        /*
        Get an instance of the Database
        @return Instance
        */
        public static function getInstance()
        {
            if(!self::$_instance) // If no instance then make one
            { 
                self::$_instance = new self();
            }
            return self::$_instance;
        }

        // Constructor
        private function __construct()
        {
            $this->_connection = new mysqli($this->_host, $this->_username,$this->_password, $this->_database);
            // Error handling
            if(mysqli_connect_error())
            {
                trigger_error("Failed to conencto to MySQL: " . mysql_connect_error(),E_USER_ERROR);
            }
        }

        // Magic method clone is empty to prevent duplication of connection
        private function __clone() { }

        // Get mysqli connection
        public function getConnection()
        {
            return $this->_connection;
        }
        
        public function get_data($sql)
        {
            $ret = array('STATUS'=>'ERROR','ERROR'=>'','DATA'=>array());
            
            $mysqli = $this->getConnection();
            $res = $mysqli->query($sql);
            
            if($res)
                $ret['STATUS'] = "OK";
            else
                $ret['ERROR'] = mysqli_error();            
            
            while($row = $res->fetch_array(MYSQLI_ASSOC))
            {
                $ret['DATA'][] = $row;
            }
            return $ret;
        }
        
        public function exec($sql)
        {
            $ret = array('STATUS'=>'ERROR','ERROR'=>'');

            $mysqli = $this->getConnection();
            $res = $mysqli->query($sql);
            
            if($res)
                $ret['STATUS'] = "OK";
            else
                $ret['ERROR'] = mysqli_error();
            
            return $ret;
        }

    }

Esta clase contiene 2 métodos llamados «get_data» y «exec«, el primero devuelve los datos de un «SELECT» en un array asociativo y el segundo ejecuta una consulta tipo «INSERT, UPDATE, etc … «.

Para por ejemplo hacer una consulta distinta en otra clase podríamos hacer algo así:

include_once "database.php";

class Prueba
{

     private $db;

     public function __construct()
     {
          //Obtenemos la instancia de la BD
          $this->db = Database::getConnection();
     }

     public function prueba_consulta()
     {          
          //ejecutamos una query cualquiera ...
          $sql = "SELECT * FROM usuarios LIMIT 10";

          $result = $this->db->query($sql);

          //obtenemos los resultados
          // ....

     }

}