20. Creating a method to update the file
20. Creación de un método para actualizar archivos en la base de datos
¡Hola y bienvenido de nuevo!
En esta lección vamos a crear un método crucial para la funcionalidad de traducción - el método update(). Este método nos permitirá guardar las traducciones generadas por ChatGPT directamente en nuestra base de datos. ¡Es como añadir notas adicionales a un archivo existente!
🎯 ¿Qué vamos a crear?
Vamos a crear el método update() que:
Recibe un ID de archivo, contenido traducido e idioma destino
Ejecuta una consulta UPDATE en la base de datos
Actualiza las columnas translated y lang del registro específico
Permite guardar traducciones para su reutilización futura
🔍 Contexto: ¿Por qué necesitamos este método?
Imagina que ya tienes un archivo con texto en español. Quieres traducirlo a inglés:
Archivo original en BD:
text
ID: 25
content: "Hola mundo"
translated: NULL
lang: NULL
Después de traducción:
text
ID: 25
content: "Hola mundo"
translated: "Hello world"
lang: "English"
El método update() es el que hace esta transformación en la base de datos.
🛠️ Método update()
php
/**
* Actualiza un archivo con su traducción e idioma
*
* @param int $fileID ID del archivo a actualizar
* @param string $content Texto traducido
* @param string $lang Idioma de la traducción
* @return void
*/
public function update($fileID, $content, $lang)
{
// 1. Preparamos la consulta UPDATE
$stmt = $this->DB->prepare("
UPDATE `files`
SET `translated` = :content,
`lang` = :lang
WHERE `ID` = :fileID
");
// 2. Vinculamos los parámetros (seguridad contra SQL injection)
$stmt->bindParam(":content", $content, PDO::PARAM_STR);
$stmt->bindParam(":lang", $lang, PDO::PARAM_STR);
$stmt->bindParam(":fileID", $fileID, PDO::PARAM_INT);
// 3. Ejecutamos la consulta
$stmt->execute();
}
📝 Explicación detallada de la consulta UPDATE
Sintaxis SQL UPDATE:
sql
UPDATE nombre_tabla
SET columna1 = valor1, columna2 = valor2
WHERE condición;
Nuestra consulta desglosada:
sql
UPDATE `files` -- Tabla a actualizar
SET `translated` = :content, -- Nueva columna 1 (contenido traducido)
`lang` = :lang -- Nueva columna 2 (idioma destino)
WHERE `ID` = :fileID; -- Condición: solo el archivo con este ID
¡IMPORTANTE! Sin el WHERE, actualizarías TODOS los registros de la tabla.
🔍 Diferencia entre INSERT y UPDATE
Analogía:
INSERT → Escribir en una página nueva del cuaderno
UPDATE → Corregir o añadir información en una página ya escrita
🎨 Diagrama del flujo de traducción
text
┌─────────────────────────────────────────────────────────────┐
│ PROCESO COMPLETO DE TRADUCCIÓN │
├─────────────────────────────────────────────────────────────┤
│ 1. USUARIO en view.php?file=25 │
│ • Ve texto: "Hola mundo" │
│ • Selecciona: Language → "English" │
│ • Click: "Translate" │
│ │
│ 2. PHP procesa: │
│ • Configura: dataType = 'translation' │
│ • Configura: content = "Hola mundo" │
│ • Configura: lang = "English" │
│ • Llama: convert() → ChatGPT traduce │
│ • Recibe: "Hello world" │
│ │
│ 3. update() se ejecuta: │
│ • Parámetros: (25, "Hello world", "English") │
│ • SQL: UPDATE files SET translated='Hello world', │
│ lang='English' WHERE ID=25 │
│ │
│ 4. BASE DE DATOS ANTES: │
│ ┌─────┬──────────────┬──────────────┬────────┬────────┐ │
│ │ ID │ content │ translated │ lang │ type │ │
│ ├─────┼──────────────┼──────────────┼────────┼────────┤ │
│ │ 25 │ Hola mundo │ NULL │ NULL │ audio │ │
│ └─────┴──────────────┴──────────────┴────────┴────────┘ │
│ │
│ 5. BASE DE DATOS DESPUÉS: │
│ ┌─────┬──────────────┬──────────────┬────────┬────────┐ │
│ │ ID │ content │ translated │ lang │ type │ │
│ ├─────┼──────────────┼──────────────┼────────┼────────┤ │
│ │ 25 │ Hola mundo │ Hello world │ English│ audio │ │
│ └─────┴──────────────┴──────────────┴────────┴────────┘ │
│ │
│ 6. USUARIO ve resultado: │
│ • Texto original: "Hola mundo" │
│ • Traducción: "Hello world" │
│ • Guardado para futuras consultas │
└─────────────────────────────────────────────────────────────┘
🔧 Ejemplo práctico paso a paso
Paso 1: Estado inicial de la BD
sql
SELECT * FROM files WHERE ID = 25;
-- Resultado:
-- ID: 25, content: 'Hola mundo', translated: NULL, lang: NULL
Paso 2: Llamada al método update()
php
// Después de obtener traducción de ChatGPT
$fileID = 25;
$translatedText = "Hello world";
$language = "English";
$whisperObj->update($fileID, $translatedText, $language);
Paso 3: Consulta SQL generada
sql
-- PHP/PDO ejecuta esta consulta (con valores seguros):
UPDATE `files`
SET `translated` = 'Hello world',
`lang` = 'English'
WHERE `ID` = 25;
Paso 4: Estado final de la BD
sql
SELECT * FROM files WHERE ID = 25;
-- Resultado:
-- ID: 25, content: 'Hola mundo', translated: 'Hello world', lang: 'English'
Paso 5: Visualización en view.php
php
<?php if($file->translated !== NULL): ?>
<li id="translateContent" class="flex flex-col my-5 w-full">
<h3 class="text-2xl"><?php echo $file->lang; ?></h3>
<div><?php echo $file->translated; ?></div>
</li>
<?php endif; ?>
💡 Importancia de los tipos de datos en bindParam()
Corrección importante:
php
// ERROR en el código original:
$stmt->bindParam(":fileID", $fileID, PDO::PARAM_STR); // ← STR para ID?
// CORRECTO:
$stmt->bindParam(":fileID", $fileID, PDO::PARAM_INT); // ← INT para ID
¿Por qué es importante?
PDO::PARAM_INT → Trata el valor como número entero
PDO::PARAM_STR → Trata el valor como texto (string)
Los IDs son números, no texto
Mejora el rendimiento y seguridad
📊 Estructura completa de la tabla files
sql
-- Estructura óptima de la tabla:
CREATE TABLE files (
ID INT AUTO_INCREMENT PRIMARY KEY,
fileUrl VARCHAR(255) NOT NULL, -- Ruta del archivo
content TEXT NOT NULL, -- Texto original
type ENUM('audio', 'video') NOT NULL, -- Tipo de archivo
translated TEXT NULL, -- Texto traducido (puede ser NULL)
lang VARCHAR(50) NULL, -- Idioma de traducción (puede ser NULL)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Campos importantes:
translated → TEXT que permite NULL (inicialmente vacío)
lang → VARCHAR que permite NULL (inicialmente vacío)
NULL vs vacío ('') → NULL significa "aún no traducido"
🎯 Ventajas de guardar traducciones en BD
1. Evita reprocesamiento costoso:
php
// SIN guardar en BD:
// Cada vez que usuario pide traducción → llama a ChatGPT → paga por API
// CON guardado en BD:
// Primera vez: ChatGPT → paga
// Segunda vez: Lee de BD → GRATIS
2. Historial completo:
Usuario puede ver todas las traducciones previas
Puede comparar traducciones en diferentes idiomas
Puede revertir a versiones anteriores
3. Rendimiento mejorado:
Lectura desde BD: ~10ms
Llamada a ChatGPT API: ~500-2000ms
50-200 veces más rápido después de la primera traducción
🔍 Mejoras potenciales al método
Versión mejorada con validación:
php
public function update($fileID, $content, $lang)
{
// Validar que el archivo existe antes de actualizar
$existingFile = $this->getFileById($fileID);
if(!$existingFile) {
$this->error = "Archivo no encontrado";
return false;
}
// Validar que el contenido no esté vacío
if(empty(trim($content))) {
$this->error = "El contenido traducido no puede estar vacío";
return false;
}
// Preparar y ejecutar consulta
$stmt = $this->DB->prepare("
UPDATE `files`
SET `translated` = :content,
`lang` = :lang,
`updated_at` = NOW() -- Registrar fecha de actualización
WHERE `ID` = :fileID
");
$stmt->bindParam(":content", $content, PDO::PARAM_STR);
$stmt->bindParam(":lang", $lang, PDO::PARAM_STR);
$stmt->bindParam(":fileID", $fileID, PDO::PARAM_INT);
return $stmt->execute(); // Retorna true/false
}
Ventajas de la versión mejorada:
✅ Validación de existencia del archivo
✅ Validación de contenido no vacío
✅ Registro de fecha de actualización
✅ Retorno de estado (éxito/fracaso)
✅ Manejo de errores apropiado
⚠️ Consideraciones de seguridad
1. SQL Injection (ya prevenido):
php
// SEGURO gracias a bindParam()
$stmt->bindParam(":fileID", $fileID, PDO::PARAM_INT);
// INSECURO (nunca hacer esto):
$query = "UPDATE files SET translated='$content' WHERE ID=$fileID";
2. XSS (Cross-Site Scripting):
php
// Al mostrar contenido, siempre escapar:
echo htmlspecialchars($file->translated, ENT_QUOTES, 'UTF-8');
3. Validación de permisos (futuro):
php
// Si implementas usuarios:
if($file->user_id !== $_SESSION['user_id']) {
die("No tienes permiso para actualizar este archivo");
}
📊 Comparación: save() vs update()
💡 Casos de uso adicionales para update()
1. Corregir transcripción:
php
// Si el usuario encuentra un error en el texto transcrito
$whisperObj->update($fileID, $textoCorregido, NULL);
// Solo actualiza contenido, no idioma
2. Multiples traducciones (futuro):
php
// Tabla separada para múltiples traducciones
public function addTranslation($fileID, $content, $lang, $translationType = 'chatgpt')
{
$stmt = $this->DB->prepare("
INSERT INTO translations (file_id, content, lang, type)
VALUES (:fileID, :content, :lang, :type)
");
// ...
}
3. Metadatos adicionales:
php
// Agregar información sobre la traducción
public function updateWithMetadata($fileID, $translated, $lang, $translator = 'chatgpt', $confidence = 0.95)
{
$stmt = $this->DB->prepare("
UPDATE files
SET translated = :translated,
lang = :lang,
translator = :translator,
confidence_score = :confidence,
translated_at = NOW()
WHERE ID = :fileID
");
// ...
}
🎯 Puntos Clave para Recordar
UPDATE modifica, INSERT crea nuevo
WHERE es CRÍTICO → Sin él, actualizas TODA la tabla
bindParam() con tipo correcto → PARAM_INT para IDs
NULL vs vacío → NULL significa "no traducido aún"
Ventaja principal → Evita llamadas repetidas a API costosas
Siempre validar → Que archivo exista, que contenido no esté vacío
📋 Cuestionario de Repaso
Pregunta 1:
¿Qué pasa si ejecutamos UPDATE files SET translated='hola' SIN cláusula WHERE?
a) Solo se actualiza el primer registro
b) Se actualizan TODOS los registros de la tabla
c) La consulta falla con error
d) Solo se actualizan los registros con translated=NULL
Pregunta 2:
¿Por qué usamos PDO::PARAM_INT para fileID en bindParam()?
a) Porque los IDs siempre son números enteros
b) Para seguridad y optimización (tratarlo como número, no texto)
c) Porque UPDATE solo acepta parámetros enteros
d) Porque es requerido por la cláusula WHERE
Pregunta 3:
¿Qué ventaja principal tiene guardar traducciones en la BD?
a) Hace que la página se vea más bonita
b) Evita llamadas repetidas y costosas a la API de ChatGPT
c) Permite traducir a más idiomas
d) Mejora la calidad de las traducciones
Pregunta 4:
¿Qué diferencia hay entre translated = NULL y translated = ''?
a) NULL es lo mismo que cadena vacía
b) NULL significa "no existe valor", '' significa "valor vacío"
c) NULL ocupa más espacio en la BD
d) Solo se puede usar NULL con números
Pregunta 5:
¿Qué método usarías para agregar una nueva traducción a un archivo existente?
a) save()
b) update()
c) insert()
d) modify()
📝 Respuestas del Cuestionario
b) Sin cláusula WHERE, la consulta UPDATE afecta a TODAS las filas de la tabla. Esto es un error grave que podría corromper todos los datos. Siempre usar WHERE con UPDATE.
b) PDO::PARAM_INT le dice a PDO que el valor debe tratarse como número entero, lo que previene ciertos tipos de inyección SQL y permite optimizaciones internas de la base de datos.
b) La principal ventaja es económica y de rendimiento: evitar pagar y esperar por la API de OpenAI cada vez que un usuario solicita la misma traducción. Una vez traducido, se sirve desde BD.
b) NULL significa "ausencia de valor" o "desconocido", mientras que '' (cadena vacía) es un valor conocido que simplemente está vacío. En nuestra lógica, NULL = "no traducido aún".
b) update() es para modificar registros existentes. save() es para crear nuevos registros (nuevos archivos subidos). Cada uno tiene su propósito específico.
🚀 Lo que viene después
¡Perfecto! Ahora tenemos:
✅ Método update() completo y seguro
✅ Capacidad para guardar traducciones
✅ Estructura de BD preparada para traducciones
En la próxima lección vamos a:
Implementar el formulario de traducción en view.php
Procesar solicitudes POST de traducción
Integrar ChatGPT para generar traducciones
Llamar a update() para guardar resultados
Mostrar traducciones en tiempo real
✨ ¡Excelente trabajo! Has creado la infraestructura necesaria para que las traducciones sean persistentes. Ahora los usuarios pueden traducir una vez y disfrutar para siempre.
Comentarios
Publicar un comentario