10. Creating a method to conenct with our database
Tutorial para Principiantes: Conexión Segura a Base de Datos con PHP PDO
📚 Tema del Tutorial:
"Conexión a Base de Datos MySQL usando PDO en PHP: El Puente entre tu Aplicación y los Datos"
🎯 Objetivo de Aprendizaje
Al final de este tutorial entenderás:
Qué es PDO y por qué es mejor que otras alternativas
Cómo establecer conexión segura a MySQL
Qué son los constructores en clases PHP
Cómo manejar errores de conexión apropiadamente
La diferencia entre propiedades públicas y privadas
📂 Parte 1: ¿Por qué Necesitamos una Clase de Conexión?
La Analogía del Puente Telefónico:
Imagina que tu aplicación web es una ciudad y la base de datos es otra ciudad:
text
🏙️ CIUDAD PHP (Tu aplicación)
├── 🏢 Edificios = Clases PHP
├── 🚗 Coches = Objetos
├── 👥 Ciudadanos = Datos de usuario
└️️ ❌ PROBLEMA: No puede hablar directamente con la otra ciudad
🏙️ CIUDAD MySQL (Base de datos)
├── 🏦 Bancos = Tablas
├── 📁 Archivos = Registros
├── 📋 Documentos = Datos
└️️ ❌ PROBLEMA: Habla lenguaje diferente
🌉 PUENTE PDO (Clase DB.php)
├── 📞 Línea telefónica = Conexión
├── 🗣️ Traductor = PDO
├── 🔐 Seguridad = Try/Catch
└️️ ✅ SOLUCIÓN: Conecta ambas ciudades de forma segura
Sin Conexión a Base de Datos:
text
Aplicación → "Quiero guardar este archivo"
↓
❌ No hay dónde guardarlo
❌ Datos se pierden al recargar
❌ No puede recordar usuarios
Con Conexión a Base de Datos:
text
Aplicación → "Quiero guardar este archivo"
↓
✅ Conexión PDO establecida
↓
✅ Datos guardados en MySQL
↓
✅ Recuperables después
🛠️ Parte 2: Creando la Clase DB.php - El "Constructor de Puentes"
Estructura de la Clase DB:
text
📁 backend/classes/DB.php
└── 🏗️ CLASS DB (Constructor de puentes)
├── ⚙️ MÉTODO connect()
│ ├── 🔧 Construye el puente (new PDO)
│ ├── 🔐 Prueba la conexión (try)
│ ├── 🚨 Maneja fallos (catch)
│ └── 🌉 Devuelve el puente listo (return $db)
└── 🎯 PROPÓSITO: Conectar PHP con MySQL de forma segura
Código Base de DB.php:
php
<?php
class DB{
// Este método construye y devuelve el "puente"
function connect(){
// Código para construir el puente aquí
}
}
?>
🌉 Parte 3: PDO - El "Traductor Universal" de Bases de Datos
¿Qué es PDO?
PDO (PHP Data Objects) es como un traductor profesional que sabe muchos idiomas:
text
🗣️ PDO = TRADUCTOR MULTILINGÜE
├── Habla: MySQL, PostgreSQL, SQLite, Oracle
├── Convierte: Comandos PHP → Comandos SQL
├── Protege: Contra ataques de inyección SQL
└️️ Simplifica: Misma sintaxis para todas las bases de datos
Alternativas a PDO y sus Problemas:
❌ mysql_connect() (Obsoleto):
Eliminado en PHP 7
Sin protección contra inyección SQL
Solo funciona con MySQL
❌ mysqli_connect() (Mejor pero limitado):
Solo funciona con MySQL
Sintaxis diferente para otras bases de datos
Menor flexibilidad
✅ PDO (Recomendado):
Funciona con 12+ sistemas de bases de datos
Protección integrada contra inyección
Sintaxis consistente
Moderno y mantenido
Creando la Conexión PDO:
Código explicado paso a paso:
php
$db = new PDO(
'mysql:host=localhost; dbname=MyWhisper', // 📍 Dirección del servidor + Base de datos
'root', // 👤 Usuario de MySQL
'' // 🔑 Contraseña (vacía en desarrollo local)
);
Desglose de la cadena de conexión:
text
'mysql:host=localhost; dbname=MyWhisper'
├── mysql: → Usar controlador MySQL
├── host=localhost → Servidor está en esta máquina
└── dbname=MyWhisper → Conectar a la base 'MyWhisper'
Parámetros comunes adicionales:
php
'mysql:host=localhost;dbname=MyWhisper;charset=utf8mb4'
// charset=utf8mb4 → Soporta emojis y caracteres especiales
🛡️ Parte 4: Manejo de Errores con Try/Catch - El "Sistema de Airbags"
La Analogía del Conductor y el Copiloto:
text
🚗 CONDUCIENDO (Conexión a BD)
├── 👨✈️ Conductor = Código try (intenta conectar)
├── 👨🔧 Copiloto = Código catch (maneja errores)
└️️ 🛡️ Airbag = Sistema que te protege si chocas
Estructura Try/Catch:
php
try {
// 👨✈️ INTENTA hacer esto
$db = new PDO(...);
return $db; // ✅ Si funciona, sigue adelante
} catch(PDOException $error) {
// 👨🔧 ATRAPA cualquier error que ocurra
echo 'Connection Failed: ' . $error;
// 🛡️ El "airbag" se activa, no hay caída fatal
}
Tipos de Errores que Pueden Ocurrir:
🔌 Error de conexión: Servidor MySQL apagado
🔑 Error de credenciales: Usuario/contraseña incorrectos
📛 Base de datos no existe: MyWhisper no encontrada
🚫 Permisos insuficientes: Usuario no tiene acceso
Mensajes de Error Amigables:
Código mejorado:
php
try {
$db = new PDO('mysql:host=localhost;dbname=MyWhisper', 'root', '');
return $db;
} catch(PDOException $error) {
// Mensaje más amigable para el usuario
echo '<div class="error">';
echo '<h3>⚠️ Error de Conexión a la Base de Datos</h3>';
echo '<p>No se pudo conectar con la base de datos. Detalles técnicos:</p>';
echo '<code>' . $error->getMessage() . '</code>';
echo '<p>Por favor, verifica que MySQL esté funcionando.</p>';
echo '</div>';
// También puedes registrar el error para ti
error_log('Error DB: ' . $error->getMessage());
return false; // Devuelve false en lugar de detener todo
}
🏗️ Parte 5: El Constructor __construct() - El "Inicializador Automático"
¿Qué es un Constructor?
Un constructor es como el motor que arranca automáticamente cuando compras un coche nuevo:
text
🚗 COCHE NUEVO (Objeto PHP)
├── 🚪 Abres la puerta (new Clase())
├── 🔑 Giras la llave (PHP busca __construct())
├── 🚗 Motor arranca automáticamente (ejecuta __construct())
└️️ ✅ Coche listo para conducir (objeto inicializado)
Constructor en Nuestra Clase Whisper:
Código en Whisper.php:
php
public function __construct(){
// Este código se ejecuta AUTOMÁTICAMENTE
// cuando creas: $whisperObj = new Whisper();
$db = new DB; // 🏗️ Construye el "constructor de puentes"
$this->DB = $db->connect(); // 🌉 Construye y guarda el puente
}
¿Qué está Pasando Aquí?
text
[1️⃣ Creas objeto] → $whisperObj = new Whisper();
↓
[2️⃣ PHP automáticamente] → Busca método __construct()
↓
[3️⃣ Ejecuta constructor] → Crea conexión a base de datos
↓
[4️⃣ Objeto listo] → $whisperObj tiene conexión DB incluida
Ventajas del constructor:
🤖 Automático: No necesitas llamarlo manualmente
🎯 Garantizado: Siempre se ejecuta al crear objeto
📦 Organizado: Todo en un lugar para inicialización
🔧 Configurable: Puedes pasar parámetros si necesitas
🔒 Parte 6: Visibilidad - Public vs Private - "Puertas y Ventanas"
La Analogía de la Casa:
text
🏠 CASA (Clase PHP)
├── 🚪 PUERTA PRINCIPAL (public) → Todos pueden entrar
├── 🚪 PUERTA TRASERA (private) → Solo dueños de casa
├── 🪟 VENTANA (protected) → Familia puede ver
└️️ 📍 CADA HABITACIÓN = Propiedad/Variable
En Nuestro Código:
Propiedad pública (puerta principal):
php
public $error; // 🚪 Todos pueden ver/modificar desde fuera
Propiedad privada (puerta trasera):
php
private $DB; // 🚪 Solo accesible DENTRO de la clase Whisper
Propiedad protegida (ventana):
php
protected $config; // 🪟 Accesible desde esta clase y clases hijas
¿Por qué $DB es private?
Razones de seguridad y diseño:
🔒 Encapsulación: Los detalles internos están ocultos
🛡️ Seguridad: Evita que código externo modifique la conexión
🧹 Limpieza: Código más organizado y mantenible
🎯 Control: Solo la clase Whisper maneja su conexión
Ejemplo de uso correcto:
php
// ✅ CORRECTO: Desde dentro de la clase
$this->DB->query("SELECT * FROM files");
// ❌ INCORRECTO: Desde fuera de la clase (no funciona)
$whisperObj->DB->query("SELECT..."); // Error: propiedad privada
🔗 Parte 7: El Flujo Completo de Conexión
Diagrama de Conexión Paso a Paso:
text
[1️⃣ USUARIO visita index.php]
↓
[2️⃣ index.php incluye init.php]
↓
[3️⃣ init.php carga clases]
↓ (require 'classes/DB.php')
[4️⃣ Crea $whisperObj = new Whisper()]
↓ (automáticamente ejecuta __construct)
[5️⃣ Constructor crea $db = new DB()]
↓
[6️⃣ DB::connect() crea conexión PDO]
↓ (new PDO('mysql:host=...'))
[7️⃣ Si éxito → Conexión establecida]
↓ (return $db)
[8️⃣ Conexión guardada en $this->DB]
↓
[9️⃣ $whisperObj listo con conexión DB]
↓
[🔟 Aplicación puede usar base de datos]
Código de init.php Actualizado:
php
<?php
// 📦 Cargar las "herramientas" necesarias
require 'classes/DB.php'; // 🌉 El constructor de puentes
require 'classes/Whisper.php'; // 🎤 El procesador principal
// 🏗️ Construir el objeto Whisper (automáticamente conecta a DB)
$whisperObj = new Whisper();
// ✅ ¡Ahora $whisperObj tiene conexión a DB incluida!
?>
🧪 Parte 8: Probando la Conexión - Pruebas y Depuración
Prueba 1: Conexión Exitosa
Añadir en el constructor para probar:
php
public function __construct(){
$db = new DB;
$this->DB = $db->connect();
// 🧪 PRUEBA: ¿Conectó correctamente?
if($this->DB){
echo "✅ Conectado a la base de datos exitosamente!";
} else {
echo "❌ Falló la conexión a la base de datos";
}
}
Prueba 2: Errores Intencionales
Probar diferentes escenarios de error:
Nombre de BD incorrecto:
php
// En DB.php, cambiar:
'dbname=MyWhisper' → 'dbname=BaseQueNoExiste'
// Error esperado: "Unknown database 'BaseQueNoExiste'"
Credenciales incorrectas:
php
// Cambiar usuario/contraseña
'root', '' → 'usuario_incorrecto', 'clave_incorrecta'
// Error esperado: "Access denied for user"
Servidor MySQL apagado:
php
// Cambiar host
'host=localhost' → 'host=127.0.0.2'
// Error esperado: "Connection refused"
Mensajes de Error Comunes y Soluciones:
🧩 Parte 9: Ejercicio Práctico - Tu Propia Clase de Conexión
Ejercicio 1: Clase de Conexión para Blog
Crear Database.php:
php
<?php
class Database {
private $connection;
public function __construct($host, $dbname, $user, $pass){
try {
$this->connection = new PDO(
"mysql:host=$host;dbname=$dbname;charset=utf8mb4",
$user,
$pass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
);
echo "✅ Conectado a $dbname";
} catch(PDOException $e) {
die("❌ Error de conexión: " . $e->getMessage());
}
}
public function getConnection(){
return $this->connection;
}
}
// Uso:
$db = new Database('localhost', 'mi_blog', 'root', '');
$conn = $db->getConnection();
?>
Ejercicio 2: Clase con Configuración Externa
config.php:
php
<?php
return [
'database' => [
'host' => 'localhost',
'name' => 'MyWhisper',
'user' => 'root',
'pass' => ''
]
];
?>
DatabaseConnection.php:
php
<?php
class DatabaseConnection {
private static $instance = null;
private $connection;
private function __construct(){
$config = require 'config.php';
$this->connection = new PDO(
"mysql:host={$config['database']['host']};dbname={$config['database']['name']}",
$config['database']['user'],
$config['database']['pass']
);
}
public static function getInstance(){
if(self::$instance === null){
self::$instance = new DatabaseConnection();
}
return self::$instance->connection;
}
}
// Uso (siempre misma conexión):
$db = DatabaseConnection::getInstance();
?>
📊 Parte 10: Comparación - Diferentes Métodos de Conexión
Tabla Comparativa:
Configuraciones Recomendadas para PDO:
php
$db = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 🚨 Lanza excepciones en errores
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 📋 Devuelve arrays asociativos
PDO::ATTR_EMULATE_PREPARES => false, // 🔐 Mejor seguridad
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4" // 🌍 Soporte UTF8 completo
]);
❓ Parte 11: Cuestionario de Evaluación
Pregunta 1:
¿Qué ventaja principal tiene PDO sobre mysqli?
a) Es más rápido
b) Funciona con múltiples sistemas de bases de datos ✅
c) Usa menos memoria
d) Es más antiguo y probado
Explicación: PDO es una abstracción que funciona con MySQL, PostgreSQL, SQLite, etc.
Pregunta 2:
En esta línea, ¿qué hace __construct()?
php
public function __construct(){ ... }
a) Destruye el objeto
b) Se ejecuta automáticamente al crear el objeto ✅
c) Cierra la conexión a la base de datos
d) Muestra errores en pantalla
Pregunta 3:
¿Por qué usamos try/catch al conectar a la base de datos?
a) Para hacer el código más rápido
b) Para manejar errores de conexión de forma controlada ✅
c) Para evitar usar contraseñas
d) Para conectar a múltiples bases a la vez
Pregunta 4:
En esta propiedad, ¿qué significa private?
php
private $DB;
a) Que cualquiera puede modificarla desde fuera
b) Que solo es accesible dentro de la clase ✅
c) Que se comparte entre todas las clases
d) Que es visible pero no modificable
Pregunta 5:
¿Qué pasa si la base de datos 'MyWhisper' no existe?
a) PHP la crea automáticamente
b) Se muestra un error controlado por catch ✅
c) La aplicación sigue funcionando sin base de datos
d) Se usa una base de datos temporal
Pregunta 6:
En esta cadena de conexión, ¿qué significa 'localhost'?
php
'mysql:host=localhost;dbname=MyWhisper'
a) Un servidor en internet
b) La misma computadora donde corre PHP ✅
c) Una dirección IP específica
d) Un nombre de dominio
Pregunta 7:
¿Por qué no debemos usar mysql_connect() en PHP moderno?
a) Porque fue eliminado en PHP 7 y es inseguro ✅
b) Porque es muy lento
c) Porque no soporta MySQL
d) Porque es muy complicado de usar
Respuesta correcta: a) Fue eliminado y no tiene protección contra inyección SQL.
🏆 Resumen Final - Checklist de Conexión a Base de Datos
Pasos Completados:
✅ Clase DB.php creada: backend/classes/DB.php
✅ Método connect() implementado: Con PDO y try/catch
✅ Constructor añadido a Whisper: __construct()
✅ Propiedad privada $DB creada: Para encapsular conexión
✅ Conexión probada exitosamente: Mensaje "Conectado"
✅ Manejo de errores probado: Cambiando nombre de BD
✅ init.php actualizado: Carga DB.php automáticamente
Las 7 Reglas de Oro para Conexiones a BD:
🔒 Usa siempre PDO - Moderno, seguro y flexible
🛡️ Implementa try/catch - Nunca dejes errores sin manejar
🏗️ Usa constructores - Inicialización automática y limpia
🔐 Mantén conexiones privadas - Encapsula los detalles internos
🧪 Prueba casos de error - BD inexistente, credenciales malas
📝 Registra errores - Para depuración pero no muestres detalles al usuario
🎯 Reutiliza conexiones - No crees nueva conexión en cada consulta
🚀 Próximos Pasos - Lo que Viene
Lo que Haremos en Próximas Lecciones:
💾 Guardar archivos en la base de datos
📖 Leer archivos para mostrar en la interfaz
🔄 Actualizar registros (añadir traducciones)
🗑️ Eliminar archivos de forma segura
🔍 Buscar y filtrar archivos
Ejemplo de lo que podremos hacer pronto:
php
// Guardar archivo subido en la BD
$sql = "INSERT INTO files (fileUrl, content, type) VALUES (?, ?, ?)";
$stmt = $this->DB->prepare($sql);
$stmt->execute([$rutaArchivo, $textoTranscrito, 'audio']);
// Leer archivos recientes
$sql = "SELECT * FROM files ORDER BY ID DESC LIMIT 10";
$archivos = $this->DB->query($sql)->fetchAll();
Preparando Consultas Seguras:
php
// ❌ INSEGURO (vulnerable a inyección SQL)
$sql = "SELECT * FROM users WHERE email = '$email'";
// ✅ SEGURO con PDO (protegido contra inyección)
$sql = "SELECT * FROM users WHERE email = :email";
$stmt = $db->prepare($sql);
$stmt->execute([':email' => $email]);
📚 Recursos para Aprender Más
Funciones PDO importantes a aprender:
prepare() - Prepara consultas seguras
execute() - Ejecuta consultas preparadas
fetch() - Obtiene una fila de resultados
fetchAll() - Obtiene todas las filas
rowCount() - Cuenta filas afectadas
lastInsertId() - Obtiene último ID insertado
Proyectos para Practicar Conexiones a BD:
📝 Sistema de comentarios - Guardar/leer comentarios
👤 Registro de usuarios - Crear/validar cuentas
🛒 Carrito de compras - Guardar productos seleccionados
📊 Panel de estadísticas - Registrar y mostrar métricas
¡Excelente trabajo! 🎉 Has creado el componente más crítico de cualquier aplicación web: la conexión segura a base de datos. Este "puente" permitirá que tu aplicación guarde, recupere y gestione datos persistentemente.
💡 Consejo final para producción:
Cuando pases a producción:
🔑 Usa contraseñas seguras - Nunca vacías
🌍 Cambia 'localhost' - Por la IP/DNS del servidor DB
📊 Separa configuraciones - En archivo aparte (config.php)
🚀 Usa conexiones persistentes - Mejor rendimiento
📈 Monitorea conexiones - Para detectar problemas temprano
🔌 ¡Ahora tu aplicación tiene una línea directa con la base de datos! El siguiente paso: guardar información valiosa en ella
Comentarios
Publicar un comentario