En la parte 1 de esta guía eché un vistazo a la HTTP API en general. Aprendimos qué es HTTP, hablamos de la estructura de las peticiones y respuestas HTTP y de cómo los tipos de acción y las URLs se unen para determinar lo que recibes a cambio de tu petición. En esta entrada vamos a echar un vistazo a la HTTP API de WordPress.

La HTTP API de WordPress

Desde la versión 2.7 aproximadamente, WordPress ha tenido una API para manejar HTTP. Se compone de 9 funciones, de las cuales probablemente sólo utilizarás un par. Las funciones se pueden clasificar en dos grupos distintos: uno para hacer peticiones y otro para leer los resultados.

wp_remote_get(), wp_remote_post(), wp_remote_head() utilizan los métodos GET, POST y HEAD respectivamente para solicitar datos de una URL determinada. La función wp_remote_request() es una función general que permite especificar una URL y un método que la acompañe.

Las funciones utilizadas para leer las respuestas son igualmente autodescriptivas. wp_remote_retrieve_body() obtiene el cuerpo de la respuesta, la función wp_remote_retrieve_header() obtiene una cabecera con nombre. La función wp_remote_retrieve_headers() devuelve todas las cabeceras en forma de array, wp_remote_retrieve_response_code() le da el código de respuesta y wp_remote_retrieve_response_message() devuelve el mensaje de respuesta.

Eso es básicamente todo lo que hay que hacer, todo lo que necesitamos saber es cómo especificar las cabeceras para hacer las peticiones adecuadas.

Hacer peticiones

Usemos la función wp_remote_get() para hacer una petición. Usaremos el primer parámetro para establecer la URL y el segundo para añadir argumentos. Puedes encontrar el conjunto completo de parámetros soportados en The Codex, me centraré en la información de la cabecera aquí.

Para obtener el mensaje de estado de un usuario de Twitter tendrás que utilizar la ruta statuses/user_timeline.json junto con la URL https://api.twitter.com/1.1 y pasar un token de portador para la autenticación – que he generado anteriormente. El token de portador necesita ser añadido como una cabecera de autorización en la forma de Bearer [TOKEN].

$token = 'Sijbwrf82wdaBief'; 
$response = wp_remote_get('https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=kinsta', array(
    'headers' => array(
        'Authorization' => 'Bearer ' . $token
    ),
));

Al hacer esta petición se devuelve una gran cantidad de información que se puede obtener imprimiendo la variable $response. También puede utilizar las funciones de tipo wp_remote_retrieve para obtener una parte de la respuesta.

La mayoría de las veces el cuerpo contiene la información necesaria, normalmente en formato JSON. En PHP podemos convertir eso en un array con facilidad:

$data = json_decode( $response['body'], true ) 

Acceso a la API de Github

Vamos a construir un ejemplo rápido que listará nuestros últimos repos de Github en un widget de WordPress. En primer lugar, tendrás que iniciar sesión en Github e ir a tu perfil, editarlo e ir a «Personal access tokens» donde puedes generar un token.

Github Access Tokens
Github Access Tokens

Como siguiente paso, vamos a crear una plantilla de widget vacía. Este widget tendrá dos opciones: un lugar para que añadas tu token de API y un título. Este no es el mejor método ya que guarda tu token en la base de datos, pero está bien para nuestros propósitos de ejemplo.

class My_Github_Widget extends WP_Widget {

	public function __construct() {
		parent::__construct(
			'my_github_widget',
			'My Github Repos',
			array( 'description' => 'A widget that showcases your Github repos' )
		);
	}

	public function widget( $args, $instance ) {
		// Widget output
	}

	public function form( $instance ) {
		$token = ! empty( $instance['token'] ) ? $instance['token'] : '';
		$title = ! empty( $instance['title'] ) ? $instance['title'] : 'From Github';
		?>
<label for="get_field_id( 'title' ); ?>">Title <input class="widefat" id="get_field_id( 'title' ); ?>" name="get_field_name( 'title' ); ?>" type="text" value="">

<label for="get_field_id( 'token' ); ?>">Github API Token <input class="widefat" id="get_field_id( 'token' ); ?>" name="get_field_name( 'token' ); ?>" type="text" value="">

<?php } }

No quiero entrar demasiado en cómo se crean los widgets aquí. Si quieres saber más, echa un vistazo a la guía de la API de Widgets en el Códice. Lo importante es que el contenido del método widget() mostrará el contenido de nuestro widget. Dentro de esa función, nos conectaremos a Github usando una petición HTTP y luego formatearemos y daremos salida a la respuesta. Así es como se hace todo esto – todo el código siguiente va en el método widget().

echo $args['before_widget']; 

if ( ! empty( $instance['title'] ) ) { 
  echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ). $args['after_title']; 
} 

$args = array( 
  'headers' => array( 
    'Accept' => 'application/vnd.github.v3+json', 
    'Authorization' => 'token 3f4f654ab31c2f15e839c74c952e5de2f562f1ee' 
  ) 
); 

$response = wp_remote_get( 'https://api.github.com/user/repos', $args ); 
$repos = json_decode( $response['body'], true ); 

if( !empty( $repos ) ) { 
  echo '<ul>'; 
  foreach( $repos as $repo ) { 
    echo '<li><a href="' . $repo['url'] . '" target="_blank">' . $repo['name'] . '</a></li>'; 
  } 
  echo '</ul>'; 
} 

echo $args['after_widget'];

Comienza simplemente añadiendo el elemento envolvente del widget y el título en la parte superior y termina cerrando el envolvente del widget, la sección principal del código está entre los dos.

Primero configuro las cabeceras de las peticiones HTTP. La primera pregunta puede ser: ¿cómo sé qué parámetros añadir? La cabecera Authorization es la parte más importante, lo leí en la sección Authentication de los documentos de la API.

La cabecera Accept no es necesaria, pero en la parte superior de la misma página de documentos la guía te anima a proporcionarla.

Luego utilizo json_decode() en el cuerpo de la respuesta y simplemente recorro el array resultante, creando una lista de enlaces.

Próximos pasos

Si crees que es fácil, tienes toda la razón, ¡lo es! Lo difícil es asegurarse de tener todos los ángulos cubiertos sin desperdiciar recursos. Hay dos problemas con el código que requieren nuestra atención inmediata.

Si hay algún problema con la API -que puede incluir errores desconocidos, cuentas con tarifa limitada, etc.- podemos encontrarnos con un gran error. Sólo comprobamos si el cuerpo está vacío o no antes de mostrar la lista.

Si tenemos un error entre manos es probable que el cuerpo contenga información de error, por lo que tampoco estaría vacío en este caso. Es probable que enumeremos los elementos de la respuesta de error, pero como estos no tendrían las propiedades url y name terminaríamos con elementos de lista vacíos y advertencias de PHP.

El segundo problema es que esto es simplemente un desperdicio. Estamos conectando a un servicio externo en cada carga de la página que puede tomar un peaje en nuestros servidores y puede causar que la cuenta sea limitada en Github. Incluso si este no es el caso, ¿qué tan probable es que tu lista de repositorios de Github cambie entre dos vistas de página, y qué tan importante es tener información actualizada aquí?

Personalmente recomendaría usar transients en un caso como este. Un transient te permite almacenar la respuesta de la petición con un tiempo de expiración. Si estableces la caducidad en un día, los datos se recuperarán de Github una vez, y luego directamente de tu base de datos durante las siguientes 24 horas. Después de la expiración se recupera de Github de nuevo y se guarda en la base de datos.

Esto reduce sus llamadas a la API de una por carga de página a una por día, lo cual es una gran mejora y tampoco es una gran compensación.

Resumen

WordPress facilita la interacción con las API de toda la web. El uso de un par de funciones integradas te permitirá obtener datos más ricos y relevantes para tus usuarios.

Junto con el saneamiento, la comprobación de errores y un mecanismo de almacenamiento en caché, se puede construir una aplicación eficiente que no sólo es más útil, sino que consume menos recursos de lo que te podrías imaginar.

Si has utilizado la HTTP API de WordPress para conectar WordPress con una API de terceros, háznoslo saber, ¡sería estupendo conocer tu trabajo!

Daniel Pataki

Hi, my name is Daniel, I'm the CTO here at Kinsta. You may know me from Smashing Magazine, WPMU Dev, Tuts+ and other WordPress/Development magazines. Aside from WordPress and PHP I spend most of my time around Node, React, GraphQL and other technologies in the Javascript space.

When not working on making the best hosting solution in the Universe I collect board games, play table football in the office, travel or play guitar and sing in a pretty bad band.