Pregunta:
Fecha: 30-01-2015 22:43:43
(En Español)
A partir de este código quiero editar el registro correspondiente a una publicación o noticia. Este es el código:
El filtro para acceder al registro en la BdD, está en esta línea:
Estoy recién metiéndome en el PDO y la verdad estoy sumamente perdido. Pero ya como toda la comunidad de desarrolladores recomienda que uno debe pasarse al PDO etc. a como de lugar, pues bueno, qué le vamos a hacer! A por él! jajajaja :D
Por cierto, el script completo lo pueden descargar desde acá https://dl.dropboxusercontent.com/u/97286094/noticiasPDO.rar y ahí podrán probarlo y saber bien de qué se trata el asunto.
A ver si pueden ayudarme con el script. Desde ya mucha gracias. Votos: 2 - Respuestas: 17 - Vistas: 15 Compartir en: Google Facebook Twitter LinkedIn Link
¿Cómo editar un registro, con PDO y MySQL?[Resuelta]
Amigos,A partir de este código quiero editar el registro correspondiente a una publicación o noticia. Este es el código:
<?php
session_start();
require('config/index.php');
$desde = @$_GET['pag'] * 10;
$hasta = (@$_GET['pag'] * 10) + 10;
$news = $connection->prepare("SELECT id,title,content,date FROM news LIMIT $desde,$hasta");
$limite = 210;
$news->execute();
while($news1 = $news->fetch(PDO::FETCH_ASSOC)):
echo '<h3><a href="editar.php?id='.urlencode($news1['id']).'">'.$news1['title'].'</a></h3>';
echo ''.substr($news1['content'], 0, $limite).' [...]<br /><br />';
endwhile;
$count_news = $connection->query("SELECT COUNT(*) title FROM news")->fetch(PDO::FETCH_ASSOC);
for($i = 0; $i < round($count_news['title'] / 10 + 1); $i++):
echo '<a href="index.php?pag='.$i.'">'.$i.'</a>';
endfor;
//endif;
?>El filtro para acceder al registro en la BdD, está en esta línea:
echo '<h3><a href="editar.php?id='.urlencode($news1['id']).'">'.$news1['title'].'</a></h3>';
Estoy recién metiéndome en el PDO y la verdad estoy sumamente perdido. Pero ya como toda la comunidad de desarrolladores recomienda que uno debe pasarse al PDO etc. a como de lugar, pues bueno, qué le vamos a hacer! A por él! jajajaja :D
Por cierto, el script completo lo pueden descargar desde acá https://dl.dropboxusercontent.com/u/97286094/noticiasPDO.rar y ahí podrán probarlo y saber bien de qué se trata el asunto.
A ver si pueden ayudarme con el script. Desde ya mucha gracias. Votos: 2 - Respuestas: 17 - Vistas: 15 Compartir en: Google Facebook Twitter LinkedIn Link
Respuestas:
-
Fecha: 31-01-2015 10:51:17 Por favor, ¿y pueden ayudarme con esto? En la misma aplicación, quiero subir y almacenar el nombre de la foto, con este formulario:.... por cierto, la imagen sube sin problemas, a la carpeta seleccionada, pero no se almacena el nombre de a misma en la base de datos MySQL.
<?php session_start(); require('config/index.php'); if(isset($_SESSION['username'])): if(isset($_POST['news'])): if(empty($_POST['title']) || empty($_POST['content'])): echo 'Hay campos en blanco'; else: $title = $connection->prepare("SELECT title FROM news WHERE title = :title"); $title->bindParam(':title',$_POST['title']); $title->execute(); if($title->fetchColumn() == $_POST['title']): echo 'Existe una noticia con el mismo titulo'; else: $news = $connection->prepare("INSERT INTO news(id,user,title,content,foto,date,ip) VALUES ('', '".$_SESSION['username']."', :title, :content, :foto,'".date('H:i:s d/m/Y')."', :ip)"); $news->bindParam(':title',$_POST['title']); $news->bindParam(':content',$_POST['content']); $news->bindParam(':foto',$_POST['foto']); $news->bindParam(':ip',$_SERVER['REMOTE_ADDR']); if(is_uploaded_file($_FILES['foto']['tmp_name'])) { // verifica haya sido cargado el archivo $ruta= "uploads/".$_FILES['foto']['name']; // Se guardaría dentro de "fotos" con el nombre original move_uploaded_file($_FILES['foto']['tmp_name'], $ruta); if(move_uploaded_file($_FILES['foto']['tmp_name'], $_FILES['foto']['name'])) { // se coloca en su lugar final echo "<b>Upload exitoso!. Datos:</b><br>"; echo "Nombre: <i><a href=\"".$_FILES['foto']['name']."\">".$_FILES['foto']['name']."</a></i><br>"; echo "Tipo MIME: <i>".$_FILES['foto']['type']."</i><br>"; echo "Peso: <i>".$_FILES['foto']['size']." bytes</i><br>"; echo "<br><hr><br>"; } } $news->execute(); echo 'Noticia creada correctamente'; endif; endif; endif; ?> <form action="" method="post" enctype="multipart/form-data"> <input name="title" placeholder="Titulo de la noticia" size="120"><br> <br> <textarea name="content" placeholder="Contenido de la noticia" rows="10" cols="70"></textarea><br> <br> <input name="foto" type="file" id="foto" class="button" /> <br> <br> <input name="news" type="submit" value="Crear noticia"> </form> <?php endif; ?>
Me sale este error en pantalla y no se cómo resolver el asunto:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'foto' cannot be null' in ......
Por favor, de veras agradeceré mucho la ayuda de ustedes Gracias desde ya. Votos: 2 - Link respuesta -
Fecha: 31-01-2015 20:08:51 Hola Ricardo, ante todo bienvenido a la comunidad.
Estuve viendo tu script y monte un entorno de prueba para ver como se comporta.
Importante: para quien quiera hacer lo mismo deberá modificar el script "noticias23.sql" agregando arriba de todo el siguiente código:
CREATE SCHEMA noticias; USE noticias;
Con lo anterior se crea la base de datos noticias, y se la selecciona, luego el script continuará creando las tablas etc etc.
Mismo también en el archivo "noticiasPDO\config\index.php" deberán cambiar la cadena de conexión de PDO para que conecte con las credenciales correctas para su entorno. En mi caso tengo el usuario root con la contraseña en blanco (tipica instalación de XAMPP para un entorno de desarrollo local) por lo que configuré el archivo de la siguiente forma:
<?php $connection = new PDO("mysql:host=localhost;dbname=noticias","root",""); $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); ?>
Cuando corrí .../noticiasPDO/index.php obtuve un mensaje:
"Notice: A session had already been started - ignoring session_start() in..."
esto se debe a que en la linea 23 de este script hay un "session_start();" de más, se debe quitar.
Luego hice clic en el nombre de la noticia cargada "Lorem ipsum chileno" que me envió a "noticiasPDO/index.php?id=Lorem+ipsum+chileno" y nuevamente algunos errores:
Strict standards: Only variables should be passed by reference in ...\noticiasPDO\index.php on line 26
Strict standards: Only variables should be passed by reference in ...\noticiasPDO\index.php on line 56
Strict standards: Only variables should be passed by reference in ...\noticiasPDO\index.php on line 63
Se corrigen remplazando los parametros de la función "bindParam" de PDO por variables con el mismo contenido, o sea, para el primer error sería remplazar:
$news->bindParam(':title',urldecode($_GET['id']));
Por:
$id = urldecode($_GET['id']); $news->bindParam(':title',$id);
Al formulario de registro "noticiasPDO/registrer.php" lo cambiaría por:
<form action="" method="post"> <p><label>Nombre de usuario (menor a 20 caracteres):</label><br/> <input name="username" placeholder="Nombre de usuario" size="40"></p> <p><label>Contraseña:</label><br/> <input name="password" type="password" placeholder="Contraseña" id="password" size="30"></p> <p><label>Repita la contraseña:</label><br/> <input name="password2" type="password" placeholder="Repita la contraseña" id="password2" size="30"></p> <p><input name="register" type="submit" value="Registrar"> <input type="reset" name="reset" id="reset" value="Borrar formulario"></p> </form>
También recomiendo usar codificación utf8, por lo que en todos los html hay que remplazar:
<meta charset="iso-8859-2">
Por:
<meta charset="utf8">
El formulario de login "noticiasPDO/login.php" lo cambiaría por:
<form method="POST"> <p><label>Nombre de usuario (menor a 20 caracteres):</label><br/> <input name="username" placeholder="Nombre de usuario" size="40"></p> <p><label>Contraseña:</label><br/> <input name="password" type="password" placeholder="Contraseña" id="password" size="30"></p> <p><input name="register" type="submit" value="Ingresar"> <input type="reset" name="reset" id="reset" value="Borrar formulario"></p> </form>
Hasta aquí fueron ajustes rapidos, vamos al script para editar, si ejecuto: "noticiasPDO/admin.php" nuevamente hay un session_start de más:
"Notice: A session had already been started - ignoring session_start() in ...\noticiasPDO\admin.php on line 35"
quito la linea 35 y listo.
Continuando, si hago clic en la noticia a editar: "noticiasPDO/editar.php?id=1" obtengo el siguiente error:
"Notice: Undefined variable: row in ...\noticiasPDO\editar.php on line 37 Call Stack #TimeMemoryFunctionLocation 10.0004336544{main}( )..\editar.php:0"
veo que dentro del archivo falta toda la lógica php.
Siguiendo tu forma de programar hice el siguiente código:
<?php session_start(); require('config/index.php'); $id = (int) (isset($_GET['id'])) ? $_GET['id'] : 0; //if ternario if ($id == 0)) { header("Location: " . $_SERVER['HTTP_REFERER']); exit; } if ($_SERVER['REQUEST_METHOD'] == 'GET') { $query = $connection->prepare("SELECT id,title,content,date FROM news WHERE id=:id"); $query->bindParam(':id', $id); $query->execute(); $row = $query->fetch(); if (!$row) { header("Location: " . $_SERVER['HTTP_REFERER']); exit; } } elseif ($_SERVER['REQUEST_METHOD'] == 'POST') { $content = (isset($_POST['content'])) ? $_POST['content'] : ''; $title = (isset($_POST['title'])) ? $_POST['title'] : ''; $query = $connection->prepare("UPDATE news SET title = :title,content = :content WHERE id=:id"); $query->bindParam(':title', $title); $query->bindParam(':content', $content); $query->bindParam(':id', $id); $query->execute(); header("Location: admin.php"); exit; } else { header("Location: " . $_SERVER['HTTP_REFERER']); exit; } ?>
Ya con lo anterior vas a poder editar las "news" (funciona bien, lo tengo probado).
Espero que mi respuesta te sea de ayuda, con respecto al upload de archivos que mencionas, contame un poco más (¿desde dónde es que haces el upload?) a ver si te puedo dar una mano.
Saludos,
Fernando Votos: 2 - Link respuesta -
Fecha: 31-01-2015 23:03:11 Hola, estimado Fernando!
Gracias por tu valiosa ayuda. He podido resolver todo y en especial lo de la edición de la información, que sin esta alternativa el script no sirve de mucho.
Bueno, en el documento admin.php, estoy tratando de darle la funcionalidad de eliminar registros y, al mismo tiempo, hacer un unlink en la imagen correspondiente a cada noticia. EN caso contrario, al final del día tendría una cantidad de fotos perdidas, sin hacer nada, quitando espacio en la cuenta del hosting.
Bien, generé un archivo eliminar.php con el código para borrar registros y funciona de lo más bien. Pero, como comprenderás, no es la idea llegar y eliminar, sino darle al usuario la posibilidad de Cancelar. Este es el código:
<img src="img/eliminar.png" border="0" title="Eliminar" onclick="eliminarNoticia('<?php echo ''.urlencode($news1['id']).''; ?>')" style="cursor:pointer" />
El javascript es éste (va al final del documento admin.php:
<script type="text/javascript"> function eliminarNoticia(id) { if(confirm("Esta seguro que desea eliminar esta Noticia?")) { location.href="admin.php?eliminar=" + id; } } </script>Votos: 1 - Link respuesta -
Fecha: 31-01-2015 23:03:41 Y en el comienzo de la página, va este código:
<?php if(isset($_GET['eliminar'])) { //id de la Noticia $stmt = $connection->prepare('DELETE FROM news WHERE id = :id'); $stmt->bindParam(':id', $id); // this time, we'll use the bindParam method $stmt->execute(); { //UNLINK foto if(file_exists("uploads/".$img)){ unlink("uploads/".$img); } $stmt = $connection->prepare('DELETE FROM news WHERE id = :id'); }//while } ?>Votos: 1 - Link respuesta -
Fecha: 31-01-2015 23:04:13 Me sale el alerta de si deseo borrar la noticia, pero al aceptar, me sale en pantalla este error:
Warning: unlink(uploads/) [function.unlink]: Permission denied in C:\Ampps\www\sistemas-de-noticias\noticias23\admin.php on line 19
Se refieren a los enlaces unlink y creo que hay que definir .$img
Puse estas dos líneas:
$img = $news1['foto']; $id = $news1['id'];
Pero igual me sale el error señalado más arriba.
Saludos cordiales,
Ricardo Votos: 1 - Link respuesta -
Fecha: 01-02-2015 01:41:57 Dejé el unlink así
//UNLINK foto if(file_exists("uploads/".$img)){ @unlink("uploads/".$img);
Si bien ya no me sale el warning, tampoco borra la foto desde el directorio uploads Votos: 1 - Link respuesta -
Fecha: 01-02-2015 04:10:27 Hola Ricardo,
La respuesta de Fernando está súper completa, mi aporte será pequeño pero creo que te será de utilidad.
Es mala práctica el uso de la '@' en cualquier sistema. Sus usos son recomendados para situaciones muy particulares.
Es importante saber que en vez de solucionar algo estás agregando a tu código un punto de fallo que te puede generar grandes dolores de cabeza, por qué?
Porque el operador '@' no resuelve nada, lo que hace es que oculta el error y continua la ejecución del código, lo que en muchas ocasiones puede generar otros errores y fastidiarte la vida resolviendo errores superficiales sin resolver el error raíz.
Incluso con una función personalizada de captura de errores es difícil detectar el error original.
La mejor práctica es remover todos los operadores '@' de tu código para asegurar que todo funcione bien y evitarte mayores problemas después. Votos: 0 - Link respuesta -
Fecha: 01-02-2015 04:37:20 Así es, Ernesto. Me di cuenta de eso y ya eliminé el operador,que por lo demás no sirve de nada. Pero me he quedado igual. Al menos con los últimos arreglos, el enlace javascript cumple su papel y el registro se elimina exitosamente. Pero no así la foto.
Si me puedes ayudar, desde ya muy agradecido.
Saludos y buen domingo! :) Votos: 0 - Link respuesta -
Fecha: 01-02-2015 06:51:28 Ricardo intenta esto:
unlink(realpath($tuArchivo));
Unlink requiere el path completo Votos: 0 - Link respuesta -
Fecha: 01-02-2015 07:35:07 Amigos, a todo esto, no los había felicitado por este sitio. De veras me gusta mucho y está genial, se nota que le pusieron mucho cariño y profesionalismo a la hora de hacer un desarrollo de primer nivel. Los felicito y agradezco que estén siempre dispuestos a ayudar y colaborar.
Bien, continuando con mi tema, la línea que me está dando guerra es esta:
unlink('uploads/'.$img);
Pero revisando esto, me acabo de percatar que hay un dilema en todo este tema, con el formulario en editar.php. Cuando actualizo una noticia y decido cambiar la foto, no hay problemas. Le di esta funcionalidad y todo trabaja de maravillas. Pero, la foto anterior queda en la carpeta uploads no haciendo nada. ¿Cómo hago para pisar la foto añeja por la nueva?
El código del formulario es éste:
<?php require('config/index.php'); $id = (int) (isset($_GET['id'])) ? $_GET['id'] : 0; //if ternario if(($id == 0)) { header("Location: " . $_SERVER['HTTP_REFERER']); exit; } if ($_SERVER['REQUEST_METHOD'] == 'GET') { $query = $connection->prepare("SELECT id,title,content,foto,date FROM news WHERE id=:id"); $query->bindParam(':id', $id); $query->execute(); $row = $query->fetch(); if (!$row) { header("Location: " . $_SERVER['HTTP_REFERER']); exit; } } elseif ($_SERVER['REQUEST_METHOD'] == 'POST') { $content = (isset($_POST['content'])) ? $_POST['content'] : ''; $title = (isset($_POST['title'])) ? $_POST['title'] : ''; $query = $connection->prepare("UPDATE news SET title = :title,content = :content,foto = :foto WHERE id=:id"); $query->bindParam(':title', $title); $query->bindParam(':content', $content); $query->bindParam(':foto',$_FILES['foto']['name']); $query->bindParam(':id', $id); /********** Subir la foto *****************/ if(is_uploaded_file($_FILES['foto']['tmp_name'])) { // verifica haya sido cargado el archivo $ruta= "uploads/".$_FILES['foto']['name']; // Se guardaría dentro de "fotos" con el nombre original move_uploaded_file($_FILES['foto']['tmp_name'], $ruta); if(move_uploaded_file($_FILES['foto']['tmp_name'], $_FILES['foto']['name'])) { // se coloca en su lugar final echo "<b>Upload exitoso!. Datos:</b><br>"; echo "Nombre: <i><a href=\"".$_FILES['foto']['name']."\">".$_FILES['foto']['name']."</a></i><br>"; echo "Tipo MIME: <i>".$_FILES['foto']['type']."</i><br>"; echo "Peso: <i>".$_FILES['foto']['size']." bytes</i><br>"; echo "<br><hr><br>"; } } /*********** Fin subir foto *************/ $query->execute(); header("Location: admin.php"); exit; } else { header("Location: " . $_SERVER['HTTP_REFERER']); exit; } ?> <form action="" method="post" enctype="multipart/form-data"> <input name="title" placeholder="Titulo de la noticia" value="<?php echo $row['title'];?>" size="110"><br><br> <textarea name="content" placeholder="Contenido de la noticia" rows="10" cols="70"><?php echo $row['content'];?></textarea><br> <br> <input name="foto" type="file" id="foto" class="button" /> <br> <br> <input name="news" type="submit" value="Editar noticia"> </form>Votos: 0 - Link respuesta -
Fecha: 01-02-2015 07:43:40 Recuerdo que en otro sistema que funciona sin problemas, php+mysqli este código opera de mil maravillas:
$foto = $_POST['foto']; //GENERADOR DE CODIGOS ALEATORIOS $str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; $cad = ""; for($i=0;$i<15;$i++) { $cad .= substr ($str,rand (0,62),1); } $foto = $ruta = ("$cad".$_FILES['foto']['name']); if(is_uploaded_file($_FILES['foto']['tmp_name'])) { // verifica haya sido cargado el archivo $ruta= "uploads/$cad".$_FILES['foto']['name']; // Se guardaría dentro de "fotos" con el nombre original move_uploaded_file($_FILES['foto']['tmp_name'], $ruta); //****************************** Unlink! ****************************// if($_POST['foto_anterior']!="") { //Borrar Anterior if(file_exists("uploads/".$_POST['foto_anterior'])) { unlink("uploads/".$_POST['foto_anterior']); } } } else { // Ocurrio un error, la imagen no se subio al servidor $foto = $_POST['foto_anterior']; } } else { // Si estamos acá es porque ocurrieron otros errores $foto = $_POST['foto_anterior']; } // La foto se sube a la carpeta de destino if(move_uploaded_file($_FILES['foto']['tmp_name'], $_FILES['foto']['name'])) { //************************************ Fin Subir Foto y Unlink! ********************************//Votos: 0 - Link respuesta -
Fecha: 01-02-2015 07:45:21 Obviamente en el paradigma del PDO ya no va a funcionar, así es que ni he intentado siquiera probar, no tiene sentido, toda vez que me va a arrojar el mismo warning ya descrito más arriba. Votos: 0 - Link respuesta
-
Fecha: 03-02-2015 07:52:31 Ricardo, no había leído el comentario del error:
Warning: unlink(uploads/) [function.unlink]: Permission denied in C:\Ampps\www\sistemas-de-noticias\noticias23\admin.php on line 19
Este Warning es muy sencillo de resolver. Lo que está sucediendo es que el usuario del servidor no tiene los permisos para poder borrar el archivo del directorio uploads.
Asigna bien los permisos y verás como funciona correctamente. Votos: 0 - Link respuesta -
Fecha: 03-02-2015 09:04:47 Hola, Ernesto, pasa que el servidor lo tengo montado en ambiente Windows 7 y ahí no hay problemas del tipo CHMOD como sucede con Linux.
Reformulé el código, pero ni así funciona. Es éste:
<?php if(isset($_GET['eliminar'])){ //id de la Noticia $id = $_GET['eliminar']; $stmt = $connection->prepare('DELETE FROM news WHERE id = :id '); $stmt->bindParam(':id', $id); $stmt->execute();{ $destino = "../uploads/"; $filetype = $_FILES['foto']['type']; $type = substr($filetype, (strpos($filetype,"/"))+1); $types=array("jpeg","gif","png"); if(in_array($type, $types)){ if(isset($_FILES['foto'])){ $foto = $_FILES['foto']['name']; $temp = $_FILES['foto']['tmp_name']; } } /* if(isset($_GET['foto'])); $img = $news1['foto']; $id = $news1['id']; $realpath = realpath( "uploads/" . $img ); if( $realpath ) { if( unlink( $realpath ) ) { echo "Imagen eliminada."; } else { echo "No se pudo eliminar la imagen."; } } */ $stmt = $connection->prepare('DELETE FROM news WHERE id = :id'); } } ?>
El enlace de borrado del registro, es éste:
<img src="img/eliminar.png" border="0" title="Eliminar" onclick="eliminarNoticia('<?php echo ''.urlencode($news1['id']).''; ?>')" style="cursor:pointer" />
Y el javascript es éste:
<script type="text/javascript"> function eliminarNoticia(id) { if(confirm("Esta seguro que desea eliminar esta Noticia?")) { location.href="admin.php?eliminar=" + id; } } </script>Votos: 1 - Link respuesta -
Fecha: 03-02-2015 09:05:42 Y, repito, ni así funciona. Al menos ya no me sale el Warning, con eso no hay problemas. Pero la foto queda en el servidor, no haciendo nada.
Quizás tengo que asociar el registro a eliminar con la correspondiente foto, pero no se cómo se hace para que el sistema reconozca que el registro tiene una foto específica, que debe ser eliminada cuando pincho el enlace con comportamiento javascript. Votos: 0 - Link respuesta -
Fecha: 04-02-2015 07:07:15 Hola Ricardo, Ojo! Windows de hecho tambien maneja permisos y usuarios. Ya he tenido un par de problemas asi en otras instalaciones.
Regresando a tu pregunta, tienes varias cosas que hacer y que tu mismo ya te has contestado. Debes definir que imagen quieres quitar, en tus scripts no hay declaracion de la ruta o del nombre de imagen. Al menos no que yo vea en los scripts que pegaste aqui. Una vez que tengas el nombre de la imagen te sera muy sencillo eliminarla. Votos: 0 - Link respuesta -
Fecha: 04-02-2015 08:12:32 Sí, el nombre de la imagen, o sea, el campo, es $foto. Pero no se cómo invocarla. Votos: 0 - Link respuesta
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión
