ScotlandPHP 2016

Conexiones y su administración

Las conexiones se establecen creando instancias de la clase base PDO. No importa el controlador que se utilice; siempre se usará el nombre de la clase PDO. El constructor acepta parámetros para especificar el origen de la base de datos (conocido como DSN) y, opcionalmente, el nombre de usuario y la contraseña (si la hubiera).

Ejemplo #1 Conectarse a MySQL

<?php
$mbd 
= new PDO('mysql:host=localhost;dbname=prueba'$usuario$contraseña);
?>

Si hubieran errores de conexión, se lanzará un objeto PDOException. Se puede capturar la excepción si fuera necesario manejar la condición del error, o se podría optar por dejarla en manos de un manejador de excepciones global de aplicación configurado mediante set_exception_handler().

Ejemplo #2 Manejo de errores de conexión

<?php
try {
    
$mbd = new PDO('mysql:host=localhost;dbname=prueba'$usuario$contraseña);
    foreach(
$mbd->query('SELECT * from FOO') as $fila) {
        
print_r($fila);
    }
    
$mbd null;
} catch (
PDOException $e) {
    print 
"¡Error!: " $e->getMessage() . "<br/>";
    die();
}
?>

Advertencia

Si la aplicación no captura la excepción lanzada por el constructor de PDO, la acción predeterminada que toma el motor zend es la de finalizar el script y mostrar información de seguimiento. Esta información probablemente revelará todos los detalles de la conexión a la base de datos, incluyendo el nombre de usuario y la contraseña. Es su responsabilidad capturar esta excepción, ya sea explícitamente (con una sentencia catch) o implícitamente por medio de set_exception_handler().

Una vez realizada con éxito una conexión a la base de datos, será devuelta una instancia de la clase PDO al script. La conexión permanecerá activa durante el tiempo de vida del objeto PDO. Para cerrar la conexión, es necesario destruir el objeto asegurándose de que todas las referencias a él existentes sean eliminadas; esto se puede hacer asignando NULL a la variable que contiene el objeto. Si no se realiza explícitamente, PHP cerrará automáticamente la conexión cuando el script finalice.

Nota: Si aún existen otras referencias a esta instancia de PDO (tales como desde una instancia de PDOStatement, o desde otras variables que hacen referencia a la misma instancia de PDO), estas también han de eliminarse (por ejemplo, asignando NULL a la variable que hace referencia al PDOStatement).

Ejemplo #3 Cerrar una conexión

<?php
$mbd 
= new PDO('mysql:host=localhost;dbname=prueba'$usuario$contraseña);
// Utilizar la conexión aquí
$sth $mbd->query('SELECT * FROM foo');

// Ya se ha terminado; se cierra
$sth null;
$mbd null;
?>

Muchas aplicaciones web se beneficiarán del uso de conexiones persistentes a servidores de bases de datos. Las conexiones persistentes no son cerradas al final del script, sino que son almacenadas en caché y reutilizadas cuando otro script solicite una conexión que use las mismas credenciales. La caché de conexiones persistentes permite evitar la carga adicional de establecer una nueva conexión cada vez que un script necesite comunicarse con la base de datos, dando como resultado una aplicación web más rápida.

Ejemplo #4 Conexiones persistentes

<?php
$mbd 
= new PDO('mysql:host=localhost;dbname=prueba'$usuario$contraseña, array(
    
PDO::ATTR_PERSISTENT => true
));
?>

Nota:

Para utilizar conexiones persistentes, se deberá establecer PDO::ATTR_PERSISTENT en las opciones del array del controlador pasado al constructor de PDO. Si este atributo se establece con PDO::setAttribute() después de la instanciación del objeto, el controlador no utilizará conexiones persistentes.

Nota:

Si se usa el controlador PDO y las bibliotecas ODBC admiten el aprovisionamiento de conexiones ODBC (unixODBC y Windows lo hacen; podrían haber más), se recomienda no utilizar las conexiones persistentes de PDO, y, en su lugar, dejar el almacenamiento en caché de conexiones a la capa del aprovisionamiento de conexiones de ODBC. La provisión de conexiones de ODBC se comparte con otros módulos en el proceso; si se le indica a PDO que almacene en caché la conexión, entonces dicha conexión nunca será devuelta a la provisión de conexiones de ODBC, dando como resultado la creación de conexiones adicionales para servir a los demás módulos.

add a note add a note

User Contributed Notes 8 notes

up
133
cappytoi at yahoo dot com
2 years ago
Using PHP 5.4.26, pdo_pgsql with libpg 9.2.8 (self compiled). As usual PHP never explains some critical stuff in documentation. You shouldn't expect that your connection is closed when you set $dbh = null unless all you do is just instantiating PDO class. Try following:

<?php
$pdo
= new PDO('pgsql:host=192.168.137.1;port=5432;dbname=anydb', 'anyuser', 'pw');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM sometable');
$stmt->execute();
$pdo = null;
sleep(60);
?>

Now check your database. And what a surprise! Your connection hangs for another 60 seconds. Now that might be expectable because you haven't cleared the resultset.

<?php
$pdo
= new PDO('pgsql:host=192.168.137.160;port=5432;dbname=platin', 'cappytoi', '1111');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM admin');
$stmt->execute();
$stmt->closeCursor();
$pdo = null;
sleep(60);
?>

What teh heck you say at this point? Still same? Here is what you need to do to close that connection:

<?php
$pdo
= new PDO('pgsql:host=192.168.137.160;port=5432;dbname=platin', 'cappytoi', '1111');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM admin');
$stmt->execute();
$stmt->closeCursor(); // this is not even required
$stmt = null; // doing this is mandatory for connection to get closed
$pdo = null;
sleep(60);
?>

PDO is just one of a kind because it saves you to depend on 3rd party abstraction layers. But it becomes annoying to see there is no implementation of a "disconnect" method even though there is a request for it for 2 years. Developers underestimate the requirement of such a method. First of all, doing $stmt = null  everywhere is annoying and what is most annoying is you cannot forcibly disconnect even when you set $pdo = null. It might get cleared on script's termination but this is not always possible because script termination may delayed due to slow client connection etc.

Anyway here is how to disconnect forcibly using postgresql:

<?php
$pdo
= new PDO('pgsql:host=192.168.137.160;port=5432;dbname=platin', 'cappytoi', '1111');
sleep(5);
$stmt = $pdo->prepare('SELECT * FROM admin');
$stmt->execute();
$pdo->query('SELECT pg_terminate_backend(pg_backend_pid());');
$pdo = null;
sleep(60);
?>

Following may be used for MYSQL: (not guaranteed)
KILL CONNECTION_ID()
up
24
jak dot spalding at gmail dot com
5 years ago
Just thought I'd add in and give an explanation as to why you need to use 127.0.0.1 if you have a different port number.

The mysql libraries will automatically use Unix sockets if the host of "localhost" is used. To force TCP/IP you need to set an IP address.
up
5
ogierschelvis at gmail dot com
9 months ago
As http://stackoverflow.com/questions/17630772/pdo-cannot-connect-remote-mysql-server points out; sometimes when you want to connect to an external server like this:

<?php
$conn
= new PDO('mysql:host=123.4.5.6;dbname=test_db;port=3306','username','password');
?>

it will fail no matter what. However if you put a space between mysql: and host like this:

<?php
$conn
= new PDO('mysql: host=123.4.5.6;dbname=test_db;port=3306','username','password');
?>

it will magically work. I'm not sure if this applies in all cases or server setups. But I think it's worth mentioning in the docs.
up
7
thz at plista dot com
3 years ago
If you are using PHP 5.4 and later, you can no longer use persistent connections when you have your own database class that derives from the native PDO object. If you do, you will get segmentation faults during the PHP process shutdown.

Please see this bug report for more information: https://bugs.php.net/bug.php?id=63176
up
9
dan dot franklin at pearson dot com
8 years ago
Note that you can specify a port number with "port=####", but this port number will be ignored if the host is localhost.  If you want to connect to a local port other than the default, use host=127.0.0.1 instead of localhost.
up
11
neville at whitespacers dot com
6 years ago
To avoid exposing your connection details should you fail to remember to catch any exception thrown by the PDO constructor you can use the following class to implicitly change the exception handler temporarily.

<?php

Class SafePDO extends PDO {

        public static function
exception_handler($exception) {
           
// Output the exception details
           
die('Uncaught exception: ', $exception->getMessage());
        }

        public function
__construct($dsn, $username='', $password='', $driver_options=array()) {

           
// Temporarily change the PHP exception handler while we . . .
           
set_exception_handler(array(__CLASS__, 'exception_handler'));

           
// . . . create a PDO object
           
parent::__construct($dsn, $username, $password, $driver_options);

           
// Change the exception handler back to whatever it was before
           
restore_exception_handler();
        }

}

// Connect to the database with defined constants
$dbh = new SafePDO(PDO_DSN, PDO_USER, PDO_PASSWORD);

?>
up
1
edsanhu at gmail dot com
9 months ago
For being able to retrieve information from the db in utf-8 the connection assignment has to add to the dsn `charset=utf8`:

<?php
$dbh
= new PDO('mysql:host=localhost;dbname=test;charset=utf8', $user, $pass);
?>
up
1
alvaro at demogracia dot com
5 years ago
On connection errors, the PDO constructor seems to do two things no matter your PDO::ATTR_ERRMODE setting:

1. Trigger a warning
2. Throw a PDOException

If you set the PDO::ATTR_ERRMODE parameter, it will only take effect on further operations.
To Top