Conectar PHP con MySQL
PHP y MySQL han sido compañeros inseparables desde los inicios de la web dinámica. PHP ofrece dos extensiones para conectarse a MySQL: PDO (PHP Data Objects) y MySQLi. En este artículo aprenderás a usar ambas, aunque nos centraremos en PDO por ser la opción recomendada gracias a su compatibilidad con múltiples bases de datos y su API más limpia para trabajar con sentencias preparadas.
Requisitos previos
Necesitas PHP 7.4 o superior con las extensiones pdo_mysql y mysqli habilitadas. En la mayoría de las instalaciones de PHP estas extensiones vienen activadas por defecto. Puedes verificarlo ejecutando php -m | grep -i mysql en la terminal o revisando la salida de phpinfo().
Instalación
PHP incluye PDO y MySQLi como extensiones nativas, así que no necesitas instalar paquetes adicionales. Solo asegúrate de que estén habilitadas en tu archivo php.ini:
// Verifica que estas líneas no estén comentadas en php.ini
// extension=pdo_mysql
// extension=mysqliCódigo completo
Este ejemplo establece una conexión con MySQL usando PDO, ejecuta una consulta de prueba y cierra la conexión:
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=tienda;charset=utf8mb4',
'root',
'tu_contraseña',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
$stmt = $pdo->query('SELECT 1 + 1 AS resultado');
$fila = $stmt->fetch();
echo "Conexión exitosa. Resultado: {$fila['resultado']}\n";
} catch (PDOException $e) {
echo "Error de conexión: {$e->getMessage()}\n";
}Salida esperada:
Conexión exitosa. Resultado: 2
Explicación paso a paso
La clase PDO recibe tres argumentos principales: el DSN (Data Source Name), el usuario y la contraseña. El DSN especifica el driver (mysql), el host, el nombre de la base de datos y el charset. El cuarto argumento es un array de opciones que configuran el comportamiento de PDO.
Las opciones más importantes son:
<?php
$opciones = [
// Lanzar excepciones en errores (recomendado)
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// Devolver arrays asociativos por defecto
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// Usar sentencias preparadas reales del servidor
PDO::ATTR_EMULATE_PREPARES => false,
// Usar conexiones persistentes (opcional)
PDO::ATTR_PERSISTENT => false,
// Timeout de conexión en segundos
PDO::ATTR_TIMEOUT => 5
];
$dsn = 'mysql:host=localhost;port=3306;dbname=tienda;charset=utf8mb4';
$pdo = new PDO($dsn, 'root', 'tu_contraseña', $opciones);
echo "Conectado a MySQL. Versión: " . $pdo->getAttribute(PDO::ATTR_SERVER_VERSION) . "\n";
echo "Driver: " . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . "\n";Salida esperada:
Conectado a MySQL. Versión: 8.0.35
Driver: mysql
Desactivar EMULATE_PREPARES es importante porque obliga a PDO a usar las sentencias preparadas nativas del servidor MySQL en lugar de emularlas en PHP. Esto mejora la seguridad y permite que MySQL optimice las consultas repetitivas.
Conexión con MySQLi
MySQLi es la otra extensión disponible, específica para MySQL. Es una alternativa válida si no necesitas compatibilidad con otras bases de datos:
<?php
// Estilo orientado a objetos
$mysqli = new mysqli('localhost', 'root', 'tu_contraseña', 'tienda');
if ($mysqli->connect_error) {
die("Error de conexión: {$mysqli->connect_error}\n");
}
$mysqli->set_charset('utf8mb4');
echo "Conectado a MySQL con MySQLi. ID de hilo: {$mysqli->thread_id}\n";
$resultado = $mysqli->query('SELECT 1 + 1 AS resultado');
$fila = $resultado->fetch_assoc();
echo "Resultado: {$fila['resultado']}\n";
$mysqli->close();Función reutilizable de conexión
En una aplicación real, debes centralizar la creación de la conexión para no repetir código:
<?php
// archivo: database.php
function obtenerConexion(): PDO {
static $pdo = null;
if ($pdo === null) {
$host = getenv('DB_HOST') ?: 'localhost';
$nombre = getenv('DB_NAME') ?: 'tienda';
$usuario = getenv('DB_USER') ?: 'root';
$clave = getenv('DB_PASSWORD') ?: '';
$dsn = "mysql:host={$host};dbname={$nombre};charset=utf8mb4";
$pdo = new PDO($dsn, $usuario, $clave, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]);
}
return $pdo;
}El uso de static garantiza que solo se cree una conexión por petición HTTP, reutilizándola en todas las llamadas posteriores. Este patrón es conocido como Singleton.
Conexiones persistentes
Las conexiones persistentes se mantienen abiertas entre peticiones HTTP, lo que ahorra el costo de establecer una nueva conexión en cada petición:
<?php
$pdo = new PDO(
'mysql:host=localhost;dbname=tienda;charset=utf8mb4',
'root',
'tu_contraseña',
[
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]
);Usa conexiones persistentes con precaución. Si tu aplicación maneja muchas conexiones simultáneas, las conexiones persistentes pueden agotar el límite de conexiones del servidor MySQL.
Caso práctico
Veamos cómo estructurar la conexión en una clase de base de datos para un proyecto PHP moderno:
<?php
// archivo: src/Database.php
class Database {
private static ?PDO $instancia = null;
public static function getConnection(): PDO {
if (self::$instancia === null) {
$config = require __DIR__ . '/../config/database.php';
self::$instancia = new PDO(
"mysql:host={$config['host']};dbname={$config['database']};charset=utf8mb4",
$config['username'],
$config['password'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
}
return self::$instancia;
}
// Para pruebas: permite resetear la conexión
public static function reset(): void {
self::$instancia = null;
}
}
// archivo: config/database.php
return [
'host' => getenv('DB_HOST') ?: 'localhost',
'database' => getenv('DB_NAME') ?: 'tienda',
'username' => getenv('DB_USER') ?: 'root',
'password' => getenv('DB_PASSWORD') ?: ''
];
// Uso en cualquier parte
$pdo = Database::getConnection();
$stmt = $pdo->query('SELECT COUNT(*) AS total FROM productos');
$total = $stmt->fetch()['total'];
echo "Total de productos: {$total}\n";Manejo de errores
Los errores de conexión se capturan mediante excepciones PDOException:
<?php
function conectarConManejo(): ?PDO {
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=tienda;charset=utf8mb4',
'root',
'contraseña_incorrecta',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
return $pdo;
} catch (PDOException $e) {
$codigo = $e->getCode();
switch ($codigo) {
case 1045:
echo "Credenciales incorrectas. Verifica usuario y contraseña.\n";
break;
case 1049:
echo "La base de datos especificada no existe.\n";
break;
case 2002:
echo "No se pudo conectar al servidor MySQL. ¿Está en ejecución?\n";
break;
case 2006:
echo "El servidor MySQL ha cerrado la conexión.\n";
break;
default:
echo "Error de conexión [{$codigo}]: {$e->getMessage()}\n";
break;
}
return null;
}
}MySQL con Laravel
Si trabajas con Laravel, no necesitas gestionar conexiones PDO manualmente. Laravel ofrece dos capas de abstracción sobre MySQL:
- Query Builder: una interfaz fluida para construir consultas SQL sin escribir SQL crudo. Puedes aprender a usarlo en la guía del Query Builder de Laravel en catalán.
- Eloquent ORM: el ORM de Laravel que mapea tablas a modelos PHP con relaciones, scopes y mutadores. Consulta el tutorial de Eloquent en catalán.
Ahora que sabes cómo conectar PHP con MySQL, en el siguiente artículo aprenderás a ejecutar consultas SELECT para recuperar datos.
Escrito por Eduardo Lázaro
