Manos de persona manejando un portátil MacBook ojeando unas imágenes

Cómo subir una imagen a WP a través de su API REST desde una aplicación PHP

En el post anterior vimos cómo insertar un post en WordPress desde una aplicación PHP a través del API REST de WordPress.

En esta nueva publicación, vamos a ver los pasos a seguir para subir una imagen a WordPress y adjuntarla después como imagen destacada del post. Vamos a ir paso a paso, comentando el código a su vez.

Definir el endpoint y la ruta de la imagen

Esto no tiene más misterio que conocer el endpoint que nos ofrece la documentación de WordPress en su página oficial.

La ruta en cuestión es:

/wp/v2/media

Y el verbo a usar en la solicitud es POST

La ruta de la imagen, donde la tengamos almacenada cada uno. El código hasta ahora sería esto:

$target_url = 'https://dev.testwp/wp-json/wp/v2/media';
$images_path = $_SERVER['DOCUMENT_ROOT'] . '/img/imagen-de-prueba.jpg';

Extraemos información básica de la imagen

Pasamos ahora a definir tres aspectos importantes de la imagen:

  • El “contenido” de la imagen, que será lo que enviemos en la petición al API
  • Su MIME TYPE, que es el formato de la imagen, para que lo entienda la petición
  • El nombre del archivo a secas, sin la ruta
// Leer el archivo de imagen y obtener su contenido
$image_data = file_get_contents( $image_path );
// Extraemos su MIME TYPE
$mime_type = mime_content_type( $image_path );
// Generar el nombre del archivo para la imagen
$image_name = basename( $image_path );

Establecemos las cabeceras de la petición al API

Vamos ahora a definir las cabeceras de la petición al API REST de WP. Como es una imagen, las cabeceras deben ser diferentes a las que hacemos normalmente para insertar un post en WordPress, ya que hay que indicarle al sistema que lo que viaja en los datos es una imagen, para que la recomponga luego y la suba correctamente.

Al final una imagen son datos en su capa interna, que se disponen de tal forma que programas como Photoshop o un navegador interpretan y dan forma para que los humanos podamos verla como imagen, y no una larga cadena de caracteres alfanuméricos.

Estas son las cabeceras que deberían ir en toda petición POST para subir una imagen a través del API REST de WordPress:

// Crear los encabezados para la solicitud POST
$headers = array(
  'Content-Type: ' . $mime_type,
  'Content-Disposition: form-data; name="file"; filename="' . $image_name . '"',
  'Authorization: Basic ' . base64_encode( "$user:$password" )
);
  • El content-type contiene el MIME TYPE que hemos obtenido antes
  • El Content-Disposition es para indicarle la disposición del contenido e indicarle el nombre del archivo
  • La cabecera de Authorization es para validar que el usuario que realiza la petición tiene permisos.

Realizamos la petición con todos los datos ya reunidos

Por último, realizamos la petición completa mediante la librería curl de PHP. La petición quedaría tal que así:

// Realizar la solicitud POST para subir la imagen
$curl = curl_init( $target_url );
curl_setopt( $curl, CURLOPT_POST, true );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $image_data );
curl_setopt( $curl, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $curl, CURLOPT_VERBOSE, true );
$response = curl_exec( $curl );
curl_close( $curl );
// Decodificar la respuesta JSON
$result = json_decode( $response, true );
if ($response === false) {
  $error = curl_error($curl);
  echo 'cURL error: ' . $error;
  die;
}	
// Devolvemos el ID de la imagen generado en el WordPress
echo $result['id'] ? $result['id'] : null;

Lo más importante de aquí es indicar que en el payload de la petición sólo debe viajar la información de la imagen. Había leído por ahí que según la documentación de WordPress (yo no lo he encontrado) había que indicar título y descripción adicionalmente, pero si lo haces, la petición falla. Si sólo incluyes los datos de la imagen, se hace correctamente. En concreto esta línea:

curl_setopt( $curl, CURLOPT_POSTFIELDS, $image_data );

Las dos últimas líneas del CURL son opcionales porque estoy haciendo la petición contra un servidor cuyo certificado SSL no está firmado por una entidad de confianza, sino por mi mismo, para las pruebas.

Estas son las líneas a la que me refiero:

curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ); curl_setopt( $curl, CURLOPT_VERBOSE, true );

En el resultado final, nos devolverá un JSON con la información del medio subido. Lo decodificamos para manejarlo como un ARRAY y en $result[‘id’] estaría el nuevo ID asignado en la base de datos para esa imagen/archivo

Paso final. Asignarla como imagen destacada.

Una vez subida la imagen/archivo con su ID correspondiente, tan sólo tendríamos que modificar nuestro payload (incluyendo el ID de la imagen) en la petición que vayamos a hacer para subir un post mediante el API REST.

El payload quedaría tal que así:

$payload = array(
  'title'           => $h1,
  'content'         => $wp_content,
  'feeatured_media' => $image_id
);

Este es el payload que nos quedaría en la petición de inserción de POST mediante el API REST. Puedes ver el resto en el post que escribí anteriormente.

Si todo es correcto, el sistema insertará en el WordPress indicado un post con el título contenido en $h1, cuyo contenido será $wp_content y la imagen destacada (previamente subida) asignada será la correspondiente al ID contenido en $image_id

Espero que esta pequeña guía te haya servido de algo, ya que la escribí justo después de pegarme un poco con ello, así la tengo yo también de referencia, porque de estas cosas uno se olvida y es mejor tenerlo anotado.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *