Este tutorial cuenta cómo adjuntar imágenes a un post determinado en WordPress, insertándolas en la Librería de medios de WordPress –la base de datos de imágenes de nuestra página–, y que al añadirlas se generen automáticamente los tres tamaños, entre ellos el thumbnail, que tenemos definidos en las opciones de nuestra página; todo esto mediante un formulario, sin utilizar el gestor para nada.
Para ello necesitamos:
- Elegir una imagen y subirla al servidor, mediante un formulario adecuado.
- Recoger el archivo subido al servidor con la función move_uploaded_file() y colocarlo en la ubicación adecuada para que WordPress lo reconozca.
- Insertar la información sobre la imagen en la base de datos (las imágenes son tratadas en WordPress como un tipo más de contenido, como un post_type igual que los post o las páginas), y generar los tamaños intermedios de la imagen original.
El formulario
<!-- El tipo de codificación de datos (enctype) debe ser multipart/form-data --> <!-- la acción que ejecuta el formulario (action) debe apuntar a la ubicación adecuada: un archivo PHP o la dirección de una página según el sistema de permalinks de WordPress --> <form action="http://url.com/uploader-action" enctype="multipart/form-data" method="POST"> <!-- MAX_FILE_SIZE indica el tamaño máximo de un archivo en bytes: 3000000 equivale a 3MB --> <!-- MAX_FILE_SIZE debe preceder al input para subir la imagen, así la comprobación de tamaño se hará al principio --> <input name="MAX_FILE_SIZE" type="hidden" value="3000000" /> <!-- El valor del atributo name determina el nombre del array de la variable $_FILES --> Enviar este archivo: <input name="imagen" type="file" /> <input type="submit" value="Enviar archivo" /> </form>
La documentación en php.net sobre la carga de archivos mediante POST es muy completa y se explica por sí sola. Allí se puede encontrar un formulario tipo para subir archivos y la explicación de cómo almacena la información de los archivos subidos la variable $_FILES.
move_uploaded_file y la ubicación de los archivos subidos en WordPress
A partir de este punto lo que haremos será recoger la información subida mediante el formulario y colocarla en el lugar adecuado. Todo lo que sigue deberá estar en la ubicación a la que apunta la acción del formulario anterior.
move_uploaded_file
mueve un archivo desde una ubicación temporal hasta la definitiva dentro del servidor. La ubicación temporal se almacena dentro de la variable $_FILES
, en el array imagen (recordemos que esta denominación la hemos designado con el formulaio), y en la fila tmp_name
. La ubicación definitiva tiene que ser la carpeta en la que WordPress guarda los archivos subidos para que así los reconozca como tales.
<?php $upload_dir_var = wp_upload_dir(); // obtenemos la ubicación de los archivos subidos en nuestro WordPress $upload_dir = $upload_dir_var['path']; // obtenemos el path absoluto de la carpeta de archivos subidos $filename = basename($_FILES['imagen']['name']); // obtenemos el nombre del archivo subido con el form $filename = trim($filename); // eliminamos posibles espacios antes y después del nombre de archivo $filename = ereg_replace(" ", "-", $filename); // eliminamos posibles espacios intersticiales en el nombre de archivo $typefile = $_FILES['imagen']['type']; // obtenemos el tipo de archivo (JPG, PNG...) $uploaddir = realpath($upload_dir); // nos aseguramos de que el path de la carpeta de archivos subidos es absoluto // esto es importante, si no es absoluto no funcionará $uploadfile = $uploaddir.'/'.$filename; // formamos el nombre definitivo que tendrá el archivo $slugname = preg_replace('/\.[^.]+$/', '', basename($uploadfile)); // este es el nombre que tendrá la imagen en la base de datos de imágenes de WordPress if ( file_exists($uploadfile) ) { // si un archivo con el mismo nombre ya existe se añade un sufijo al nombre $count = "0"; while ( file_exists($uploadfile) ) { $count++; if ( $typefile == 'image/jpeg' ) { $exten = 'jpg'; } elseif ( $typefile == 'image/png' ) { $exten = 'png'; } elseif ( $typefile == 'image/gif' ) { $exten = 'gif'; } $uploadfile = $uploaddir.'/'.$slugname.'-'.$count.'.'.$exten; } } // fin if file_exists if (move_uploaded_file($_FILES['imagen']['tmp_name'], $uploadfile)) { // aquí ejecutaremos el código para insertar la imagen en la base de datos else { // mensaje de error } ?>
Insertando la imagen en la base de datos y creando los tamaños intermedios: wp_insert_attachment, wp_generate_attachment_metadata y wp_update_attachment_metadata
Una vez que hemos colocado la imagen en el lugar correcto con move_uploaded_file
, solo nos queda generar los tamaños intermedios, asociar la imagen a un post o una página y guardar esta información en la base de datos. Para ello, tres funciones: wp insert attachment
, wp_generate_attachment_metadata
y wp_update_attachment_metadata
.
<?php $post_id = '100'; // el identificador del post o página al que queremos asociar la imagen $slugname = preg_replace('/\.[^.]+$/', '', basename($uploadfile)); // tras la reubicación del archivo definimos definitivamente su nombre $attachment = array( 'post_mime_type' => $typefile, // tipo de archivo 'post_title' => $slugname, // el nombre del archivo en la Libreria de medios 'post_content' => '', // contenido extra asociado a la imagen 'post_status' => 'inherit' ); $attach_id = wp_insert_attachment( $attachment, $uploadfile, $post_id ); // se debe incluir el archivo image.php // para que la función wp_generate_attachment_metadata() funcione require_once(ABSPATH . "wp-admin" . '/includes/image.php'); $attach_data = wp_generate_attachment_metadata( $attach_id, $uploadfile ); wp_update_attachment_metadata( $attach_id, $attach_data ); ?>
El código completo que ejecuta la ubicación correcta del archivo dentro de la carpeta uploads de WordPress y su inclusión en base de datos (los dos últimos pasos):
<?php $upload_dir_var = wp_upload_dir(); // obtenemos la ubicación de los archivos subidos en nuestro WordPress $upload_dir = $upload_dir_var['path']; // obtenemos el path absoluto de la carpeta de archivos subidos $filename = basename($_FILES['imagen']['name']); // obtenemos el nombre del archivo subido con el form $filename = trim($filename); // eliminamos posibles espacios antes y después del nombre de archivo $filename = ereg_replace(" ", "-", $filename); // eliminamos posibles espacios intersticiales en el nombre de archivo $typefile = $_FILES['imagen']['type']; // obtenemos el tipo de archivo (JPG, PNG...) $uploaddir = realpath($upload_dir); // nos aseguramos de que el path de la carpeta de archivos subidos es absoluto // esto es importante, si no es absoluto no funcionará $uploadfile = $uploaddir.'/'.$filename; // formamos el nombre definitivo que tendrá el archivo $slugname = preg_replace('/\.[^.]+$/', '', basename($uploadfile)); // este es el nombre que tendrá la imagen en la base de datos de imágenes de WordPress if ( file_exists($uploadfile) ) { // si un archivo con el mismo nombre ya existe se añade un sufijo al nombre $count = "0"; while ( file_exists($uploadfile) ) { $count++; if ( $typefile == 'image/jpeg' ) { $exten = 'jpg'; } elseif ( $typefile == 'image/png' ) { $exten = 'png'; } elseif ( $typefile == 'image/gif' ) { $exten = 'gif'; } $uploadfile = $uploaddir.'/'.$slugname.'-'.$count.'.'.$exten; } } // fin if file_exists if (move_uploaded_file($_FILES['imagen']['tmp_name'], $uploadfile)) { // aquí ejecutaremos el código para insertar la imagen en la base de datos $post_id = '100'; // el identificador del post o página al que queremos asociar la imagen $slugname = preg_replace('/\.[^.]+$/', '', basename($uploadfile)); // tras la reubicación del archivo definimos definitivamente su nombre $attachment = array( 'post_mime_type' => $typefile, // tipo de archivo 'post_title' => $slugname, // el nombre del archivo en la Libreria de medios 'post_content' => '', // contenido extra asociado a la imagen 'post_status' => 'inherit' ); $attach_id = wp_insert_attachment( $attachment, $uploadfile, $post_id ); // se debe incluir el archivo image.php // para que la función wp_generate_attachment_metadata() funcione require_once(ABSPATH . "wp-admin" . '/includes/image.php'); $attach_data = wp_generate_attachment_metadata( $attach_id, $uploadfile ); wp_update_attachment_metadata( $attach_id, $attach_data ); else { // mensaje de error } ?>
Más información y solución a quebraderos de cabeza habituales
Sobre el clásico problema 0x0 una vez se ha conseguido añadir un archivo a la Librería de medios: el archivo se añade pero no se generan los tamaños intermedios. Este problema se soluciona definiendo la ruta hasta la imagen subida de manera absoluta, bien utilizando la información guardada como path en wp_upload_dir()
, bien haciendo absolutas las rutas como la función de PHP realpath()
.
En Golden Apples Design proponen un método alternativo utilizando la función media_handle_upload()
, sobre la que hay muy poca información. A mí no me ha funcionado.
9 comentarios
Muchas gracias amigo, excelente
tu explicacion, me funciono a las mil maravillas
Hola Amigo, una pregunta, el contenido de los dos últimos pasos, dentro de que archivo lo colocas?
Se puede colocar en el functions.php??
Hola Aport, el archivo functions.php está pensado para alojar funciones que vayan a ser llamadas con relativa frecuencia desde las plantillas del tema.
El código del que hablas ejecuta las acciones necesarias para llevar a cabo la subida de imágenes, así que debe estar en el archivo php al que apunte el parámetro action del formulario.
Hola!
Me he comprado una plantilla de WP para tener un espacio donde publicar información sobre mi boda, me gustaría que la gente pueda subir/publicar sus fotografias dentro de cuertos apartados que tengo para esto, pero hacerlo desde el admin panel puede resultar muy complejo para algunos usuarios… Podrías ayudarme a tener una forma muy fácil para que puedan hacerlo desde el frontend? Si hay algun costo ($) que cubrir lo platicamos, saludos. Tengo poco tiempo para resolverlo, me caso la primer semana de Octubre.
Hola Jorge,
te cuento opciones que se me ocurren para que soluciones por ti mismo el asunto en unas horas:
+ Con el plugin Contact Form 7 puedes crear un formulario y añadirlo fácilmente a cualquier página de tu web. Desde ese formulario la gente puede remitirte imágenes que tú publicarás después.
+ Puedes crear un grupo de flickr y que la gente añada a el las fotos. Luego con cualquier plugin de flickr para WordPress puedes reproducir el contenido del grupo de flickr en tu web.
Existe el plugin TDO Miniforms que permitía crear formularios que permitieran añadir contenido a una web sin pasar por el admin. Pero está fuera de desarrollo y se le han encontrado vulnerabilidades de seguridad, así que no es recomendable su uso. Para saber más o probarlo, en cualquier caso.
Otro plugin similar a TDO MiniForms, cforms. Ese está en el repositorio de plugins de WordPress. No lo he probado pero en los foros se habla bien de él.
Muy buen post. Me ayudara mucho con lo que estoy haciendo.
Gracias.
Definitivamente me ayudo mucho este post.
Gracias!
Muy buenas amigo, muchas gracias por tu explicación funciona perfectamente me ayudaste bastante un abrazo.