En nuestro post “Prueba tus WordPress Plugins con PHPUnit en Local” configuramos PHPUnit junto con Local para después hacer pruebas a nuestros plugins. Es una buena forma para mantener nuestro código a prueba de errores, entre otros beneficios.
(más…)Etiqueta: wordpress
Prueba tus WordPress Plugins con PHPUnit en Local
Cuando estamos desarrollando nuestros plugins para WordPress, lo último que se nos viene a la mente es, probarlos. Y con probarlos me refiero a integrar PHPUnit y crear pruebas para confirmar que nuestro plugin para WordPress funciona.
(más…)Desactiva código JavaScript y CSS en tu WordPress
Nuestros sitios web hechos en WordPress contienen plugins desarrollados por terceros que cargan código JavaScript y CSS desde archivos.
Hay veces que necesitamos desactivar esos archivos para mejorar el performance de nuestro sitio web.
Existen dos formas de usar el código JavaScript y CSS:
- Usando archivos
.js
y.css
. Recomendado. - Incrustándolos directo en el template de nuestro tema. No recomendado.
Inline Scripts/Styles. No recomendado
El código JavaScript y CSS puede incrustarse dentro de un template, por ejemplo, dentro de tu archivo
header.php
,footer.php
, etc.Lo puedes hacer, sí, pero no es recomendable ya que no será escalable y se te hará muy difícil identificar el código dentro de tus templates.
<?php if ( is_page_template( 'page-templates/template-easy-feature.php' ) ) { ?> <script> jQuery( document ).ready( function() { jQuery('.browse-categories-btn a').click(function() { jQuery('.browse-categories-btn a').parent().removeClass('active-categories'); jQuery(this).parent().addClass('active-categories'); }); }); </script> <?php } ?>
El código anterior demuestra un código inline script, es decir, está incrustado directamente en un archivo template de tu tema.
Los JavaScript (inline script) y CSS (inline style) que están incrustados en el template de tu tema, no serán posibles de desactivarlos.
Carga correctamente tu código JS y CSS
Cargar el código JavaScript y CSS usando archivos es lo contrario a usar inline scripts y styles. Es más fácil de identificar dónde existe tu código y mucho más fácil desactivarlos.
Ya que tengas los archivos, ahora debes registrarlos en WordPress. Cuando estamos desarrollando nuestros plugins, podemos usar dos funciones para cargar nuestro código JavaScript y CSS de forma correcta.
Para los archivos JavaScript debemos usar la función
wp_enqueue_script()
y para los CSS usamos la funciónwp_enqueue_style()
.Las funciones anteriores deben ejecutarse dentro del hook
wp_enqueue_scripts
:<?php add_action( 'wp_enqueue_scripts', 'rmr_load_assets' ); function rmr_load_assets() { wp_enqueue_script( 'wp-countup-js-plugin', WP_COUNTUP_JS_URL . 'assets/js/wp-countup-show-counter.min.js', array( 'jquery' ), WP_COUNTUP_JS_VERSION, $in_footer ); }
Los archivos JS y CSS no son cargados si las funciones anteriores no se ejecutan dentro del hook
wp_enqueue_scripts
.Ahora, verifica que el archivo ha sido cargado correctamente usando la pestaña Network en las herramientas de desarrollos de tu navegador:
JavaScript cargado por un plugin usando wp_enqueue_script(). Las funciones anteriores usan como primer parámetro el nombre (
$handle
) del JavaScript o CSS.Es muy importante que especifiques el parámetro
$handle
. Es usado para identificar el archivo dentro de todo el sistema de WordPress.Cuando cargas un archivo JS y CSS usando
wp_enqueue_script()
ywp_enqueue_style()
, estos serán guardados dentro de una variable global llamada$wp_scripts
y$wp_styles
, respectivamente.Puedes usar esas variables globales o las funciones
wp_scripts()
ywp_styles()
para editar o debuggear los JavaScript y CSS registrados.Desactiva el código JavaScript y CSS
Si los archivos JS y CSS han sido cargados correctamente usando las funciones
wp_enqueue_script()
ywp_enqueue_style()
entonces podrás desactivar esos códigos fácilmente.Existe la función
wp_dequeue_script()
ywp_dequeue_style()
para desactivar los archivos cargados por WordPress.Aquí puedes jugar con tu lógica y requerimientos del sistema, por ejemplo, puedes usar las condiciones de WordPress y condiciones de guardia para desactivar un archivo JavaScript:
<?php add_action( 'wp_enqueue_scripts', 'rmr_unload_assets' ); function rmr_unload_assets() { if ( is_page( 'contact' ) ) { wp_dequeue_script( 'wp-countup-js-plugin' ); } }
El código nos demuestra que si la página actual es
/contact
, entonces desactivará el JavaScript con el nombre ($handle
)wp-countup-js-plugin
especificado dentro de la funciónwp_dequeue_script()
ywp_dequeue_style()
.Ahora no deberías ver el archivo JavaScript cargado en tu sitio web:
JavaScript desactivado usando wp_dequeue_script(). Para los estilos es lo mismo pero usando la función
wp_dequeue_style()
.Beneficios
Cuando desactivas el código JavaScript y CSS, tu servidor ya no pedirá ese archivo desactivado y por lo tanto tu página:
- Se volverá más rápida.
- Será menos pesada.
- Mejorará el puntaje de tu sitio web en Google PageSpeed Insights.
- Reducirá el tiempo de bloqueo por scripts o estilos.
Tu sitio web agradecerá estos beneficios.
Espero hayas aprendido y apliques los conocimientos que aquí he plasmado, si tienes alguna duda y/o comentario puedes dejarlo en los comentarios.
Referencias
La mejor forma de aprender a usar las funciones de WordPress aquí mencionadas, es visitar y leer la documentación oficial:
- https://developer.wordpress.org/reference/functions/wp_enqueue_script/
- https://developer.wordpress.org/reference/functions/wp_enqueue_style/
- https://developer.wordpress.org/reference/hooks/wp_enqueue_scripts/
- https://developer.wordpress.org/reference/functions/wp_dequeue_script/
- https://developer.wordpress.org/reference/functions/wp_dequeue_style/
- Usando archivos
-
Consejos para API REST externas en WordPress
Después de un par de años, mi post sobre cómo utilizar API REST externas en WordPress sigue siendo visitada. Sin embargo, algunas personas me han contactado para pedirme consejos sobre el manejo de los datos.
Problemas al usar API REST externas en WordPress
He detectado que algunos desarrolladores, después de implementar algunas API REST externas en WordPress, éste se ve afectado en cuanto a performance.
Otros no saben dónde poner su código, si en el archivo
functions.php
o en un plugin. ¿Cuál es mejor?A continuación te daré un par de consejos al momento de desarrollar e integrar una API REST en WordPress.
Consejo #1. Cachea los resultados
Después de implementar tu API REST en WordPress, se ejecutará una petición cada vez que se recargue la página.
Quiere decir que tu página tendrá que esperar (o no muestre nada) hasta que la petición haya terminado, originando los siguientes problemas:
- Un tiempo de carga muy lento. Tal vez afecte el SEO.
- Más uso de recursos de tu servidor y posiblemente el servidor de la API REST.
La solución será cachear/guardar los resultados de la petición en nuestra base de datos, para que la próxima vez que se requieran no vuelva a ejecutarse otra petición remota.
Un diagrama de flujo puede ayudar a la explicación:
Diagrama de flujo sobre el cacheo de resultados de una petición API REST. Y en código PHP/WordPress sería:
add_action( 'wp_loaded', 'rmr_load_rick_and_morty_data' ); function rmr_load_rick_and_morty_data() { $cached_results = get_option( 'rick_and_morty_cached_results' ); if ( $cached_results ) { echo $cached_results[0]['name']; return; } $response = wp_remote_get( 'https://rickandmortyapi.com/api/character/' ); if ( is_wp_error( $response ) ) { return; } $http_code = wp_remote_retrieve_response_code( $response ); if ( 200 !== $http_code ) { return; } $results = wp_remote_retrieve_body( $response ); $results = json_decode( $results, true ); $results = $results['results']; // Contiene la información que queremos. update_option( 'rick_and_morty_cached_results', $results, 'no' ); echo $results[0]['name']; }
El código anterior guardará los personajes de la serie Rick & Morty en la base de datos de WordPress haciendo una petición a la API REST cuando la acción
wp_loaded
sea llamada. La segunda vez que se intente hacer la petición, ésta no se hará porque los datos ya existen.Consejo #2. Usar una acción para actualizar los resultados
Imagina que los resultados de la API REST ya están guardados en tu base de datos, pero digamos que uno de los datos que guardaste ya cambió en todo este tiempo.
Sí puedes ir a borrar el campo que guarda los datos en tu base de datos, pero eso no es para nada óptimo, no harás esto cada vez que haya un cambio, ¿o si?
Lo más sano y seguro es agregar un botón o cualquier otro tipo de acción (acorde a tus requerimientos) para actualizar estos datos.
Una acción puede ser un click, un evento scroll e incluso un evento periódico (cron job). Cualquier acción que tú como administrador o simple usuario pueda ejecutar.
Por ejemplo, para actualizar los datos al momento de dar click en un botón usando AJAX, la lógica sería de la siguiente forma:
Diagrama de flujo sobre la actualización de resultados de una petición API REST al ejecutar una acción. Y en código se puede representar en esta forma:
add_action( 'wp_ajax_rmr_update_api_data', 'rmr_update_api_data' ); function rmr_update_api_data() { check_ajax_referer( 'rmr_update_api_data' ); $response = wp_remote_get( 'https://rickandmortyapi.com/api/character/' ); if ( is_wp_error( $response ) ) { return; } $http_code = wp_remote_retrieve_response_code( $response ); if ( 200 !== $http_code ) { return; } $results = wp_remote_retrieve_body( $response ); $results = json_decode( $results, true ); $results = $results['results']; // Contiene la información que queremos. update_option( 'rick_and_morty_cached_results', $results, 'no' ); }
Hacemos uso de la acción
wp_ajax_{action}
, la cual ejecutará la acción AJAX desde un click o scroll, algo que ejecute el AJAX request. Después hacemos las validaciones necesarias y si todo está bien, hacemos una petición a la API REST y actualizamos los datos.Lo anterior es algo complicado para desarrolladores nuevos, pero en la web hay mucha información sobre cómo trabajar con AJAX; aquí te dejo unos recursos:
- https://codex.wordpress.org/AJAX_in_Plugins
- https://developer.wordpress.org/reference/hooks/wp_ajax_action/
- https://developer.wordpress.org/reference/functions/check_ajax_referer/
- https://developer.wordpress.org/plugins/cron/
Consejo #3. Agrega validaciones
En cualquier código siempre debes agregar validaciones para no generar errores en el log del sistema. Siempre debes programar de manera defensiva.
No ejecutes código que no va a funcionar después de hacer una petición API REST fallida.
En el caso de peticiones a API REST, mayormente debes checar lo siguiente:
- Si el resultado es un
WP_Error
. - Si el código HTTP es o no 200.
Cuando ocurre un error interno de WordPress al hacer una petición, podría ocurrir un
WP_Error
, es por eso que debes hacer esta validación:$response = wp_remote_get( 'https://rickandmortyapi.com/api/character/' ); if ( is_wp_error( $response ) ) { return; }
Y de vez en cuando, el servicio REST podría no estar funcionando y tal vez retorne distintos errores como, 401, 500, etc. En este caso no podríamos procesar los datos que queremos.
Para verificar el código HTTP se hace de la siguiente manera:
$response = wp_remote_get( 'https://rickandmortyapi.com/api/character/' ); if ( is_wp_error( $response ) ) { return; } $http_code = wp_remote_retrieve_response_code( $response ); if ( 200 !== $http_code ) { return; }
Si alguna validación anterior ocurre, el código principal ya no se ejecutará, evitando así posibles errores.
También puedes agregar validaciones extras, acorde a tus requerimientos, por ejemplo, si el HTTP es 200 pero solo quieres guardar los datos si el primer resultado equivale a un cierto valor.
Consejo #4. No guardes datos que no necesitas
Ten en cuenta que algunas API REST devuelven algunos meta datos, como la página actual, fechas de actualización, etc.
Hay que ser inteligentes al momento de manejar datos, ¿necesitas almacenar esos meta datos?
El guardar datos que no necesitas solo incrementará innecesariamente la base de datos.
Por ejemplo, la API REST que hemos estado usando sobre Rick & Morty, devuelve un campo llamado
info
:Resultado de API REST de Rick & Morty. Si en realidad necesitas los datos del campo
info
, entonces guardalos, si no, no los guardes.Con el código puedes acceder fácilmente a los datos usando arreglos (arrays):
$results = wp_remote_retrieve_body( $response ); $results = json_decode( $results, true ); $results = $results['results']; // Contiene la información que queremos. $info = $results['info']; // Contiene información no valiosa. update_option( 'rick_and_morty_cached_results', $results, 'no' );
Consejo #5. Desarrolla con plugins no con temas
Al inicio es muy común desarrollar dentro del archivo
functions.php
, el cual es el archivo principal de ejecución de funciones extras del tema activo.Trabajar ahi está bien para funciones internas del tema activo, sin embargo, cuando uno va agregar una funcionalidad extra al sitio web del cliente, no debes trabajar directamente en él.
En el caso de una funcionalidad como integrar una API REST u otra funcionalidad debes trabajar en:
- Temas hijos.
- Plugins.
Los temas hijos son una opción, pero siguen siendo atenidos al tema activo padre. Esto está bien si el cliente nunca va cambiar el tema.
Por otra parte, lo que yo recomiendo es desarrollar un plugin, de esta manera el plugin siempre quedará activo a pesar de cambiar/desactivar el tema actual. Mantiene su funcionalidad.
Conclusión
Cada uno de los consejos trabajan en conjunto y separado, y en lo personal, deben aplicarse siempre que uno trabaje con API REST.
Quedará de ti y tus requerimientos el implementar uno de estos consejos u otros que se te ocurran.
¿Crees que me faltó algún consejo? ¿Cuál agregarías?
-
Tinkerwell para desarrollo en WordPress
Tinkerwell es un editor de código para Laravel pero también funciona con WordPress. Ya no tendrás que adivinar el resultado de tus funciones en WordPress.
En ocasiones, un desarrollador quiere probar su código JavaScript o PHP antes de correrlo en el navegador. Este proceso es tedioso para PHP cuando queremos probar código complejo.
En JavaScript es fácil abrir la consola del navegador y hacer un par de pruebas de tu código. Sin embargo, en PHP las cosas se complican.
Una de las clásicas opciones para ver el resultado de un script en PHP son:
- Crear un archivo PHP y ejecutarlo desde la terminal.
- Abrir un sitio como implode.io y ejecutar tu código.
En mi opinión, las opciones anteriores funcionan para scripts sencillos. Pero ¿qué me dices cuando trabajas con un framework como WordPress? Incluyen más configuración y procesamiento para realizar una tarea.
El problema con WordPress
WordPress suele ser frustrante en cuanto a desarrollo. De vez en cuando tienes que probar el resultado de ciertas functiones internas de WP y no quieres hacer un
var_dump()
en tu archivofunctions.php
para saber ese resultado.Por ejemplo, tenemos la función
get_plugins()
la cual nos permite ver los plugins instalados en nuestro WordPress. O incluso la funciónwp_nav_menu()
para ver el HTML de nuestro menú.Son de ese tipo de funciones que necesitas saber cómo se ve el resultado antes de poder manipularlos. Así que necesitamos hacer más fácil este proceso.
Tinkerwell, un editor de código mágico
La anterior problemática cambió con un programa llamado Tinkerwell, el cual es un editor de código donde solo lo abres, escribes tu código PHP, ejecutas y ves el resultado. Tanto en local como conexiones remotas.
Originalmente está creado para ser usado con Laravel pero han ido creando, a lo que ellos llaman, “drivers” para usarlo con otras plataformas como WordPress, Drupal y entre otras.
Puedes ver la lista completa de drivers en GitHub.
Configurando Tinkerwell con WordPress
Tinkerwell nos permite abrir un directorio con una instalación WordPress. El punto más importante es que ese directorio tenga, obligatoriamente, el archivo
wp-load.php
.Yo ya tengo una instalación WordPress configurada con WAMP, así que todos esos archivos de configuración están en esta ruta de mi computadora:
D:\Programas\wamp64\www\wordpress
¡Ojo! Los servicios de PHP, MySQL y Apache (o tu stack preferido) ya deben estar encendidos.
Ahora si, en Tinkerwell damos click en el ícono de la carpeta o
CTRL+O
para seleccionar nuestro directorio WordPress.La acción anterior debe de poner el entorno de trabajo en tu instalación WordPress.
Para confirmar, dentro del editor escribe la función
home_url()
y aprietaCTRL+R
o click en el botón de play.Resultado de la función home_url()
en Tinkerwell.Si la configuración es correcta, deberías ver el enlace de tu sitio WordPress.
Probando funciones de WordPress
Este post pudo haber terminar en el párrafo anterior; sin embargo, quiero enseñarte unas funcionalides extras de Tinkerwell que pueden ser muy prácticas al momento de desarrollar en WordPress.
Caso 1: Obteniendo posts en específico
Imagina que estás desarrollando un plugin donde tienes que mostrar ciertos posts con las siguientes características:
- Deben pertenecer a la categoría “Programación” (el ID de la categoría es 4).
Para lograrlo debemos usar la función
get_posts()
con ciertos argumentos:$args = array( 'numberposts' => -1, 'category' => 4, ); get_posts( $args );
Aquí es donde te preguntas, ¿será que el resultado de mi función sea el esperado? Usemos Tinkerwell para verificar.
Mostrando los títulos de los posts de la categoría “Programación”. Sabremos si el resultado es correcto si los posts dentro de la categoría “Programación” se asemejan con los resultados en Tinkerwell.
Mostrando los posts de la categoría “Programación” en WordPress. Te invito a probar la misma función pero con diferentes argumentos, por ejemplo, obtener posts de una fecha en particular.
Caso 2: Cambiando la URL usando filtros (hooks)
Por si fuera poco, también podemos ver con anticipación cómo se verán los resultados que son cambiados por los filtros (filter hooks).
Un cliente te ha pedido que debes cambiar el resultado de la función
home_url()
bajo la condición de que si la URL actual es HTTP, la URL cambie a otro dominio.De entrada, el resultado de la función retorna el siguiente resultado:
Resultado de la función home_url()
en Tinkerwell.Ahora agregamos el filtro con el siguiente código, donde decimos que si la URL no es HTTPS deberá cambiar el valor por
https://roelmagdaleno.com
.function rmr_change_home_url( $url, $path, $scheme ) { return 'https' === $scheme ? $url : 'https://roelmagdaleno.com'; } add_filter( 'home_url', 'rmr_change_home_url', 10, 3 ); home_url();
¡Ojo! Debes llamar el filtro antes de llamar a la función principal para que este pueda ser aplicado antes de enviar el resultado final.
El resultado en Tinkerwell es aplicado correctamente.
Resultado de la función home_url()
en Tinkerwell después de usar filtros.Caso 3: Viendo resultados de shortcodes
Ahora estás trabajando con un shortcode, pero necesitas ver el resultado generado (comúnmente HTML). Digamos que el shortcode pertenece al plugin Contact Form 7.
El shortcode es el siguiente
[contact-form-7 id="50" title="Contact form 1"]
y la función principal para ejecutar un shortcode esdo_shortcode()
.Entonces el código sería de esta manera:
do_shortcode( '[contact-form-7 id="50" title="Contact form 1"]' );
Y si lo ejecutas en Tinkerwell, obtienes el HTML generado por el shortcode. De esta forma puedes ver lo que tu página renderizará al momento de llamar el shortcode.
Resultado de un shortcode en Tinkerwell. BONUS: Usando Tinkerwell con Local by Flywheel
Si usas Local by Flywheel para desarrollar en WordPress, Tinkerwell también funciona con este entorno de trabajo; sin embargo, hay que hacer un ligero cambio en el archivo
wp-config.php
.Dentro de este archivo tienes la constante
DB_HOST
que originalmente su valor eslocalhost
; si ejecutas Tinkerwell, este lanzará un error de conexión a la base de datos.Para solucionar esto, el valor correcto de la constante deberá ser
localhost:<DB_PORT>
, es decir, tenemos que especificar el puerto donde está escuchando la base de datos:define( 'DB_HOST', 'localhost:10047' );
El puerto de la base de datos lo consigues dentro de la pestaña DATABASE del programa Local.
Después de agregar este cambio, reinicia el sitio, has una prueba en Tinkerwell y no deberá haber ningún error.
-
Utiliza una API REST externa con WordPress
Los datos están en su máximo esplendor en estos últimos años y algunas empresas han liberado sus datos usando su propia API REST y, de vez en cuando, queremos mostrar esos datos en nuestro WordPress.
Al hablar de datos, se nos viene a la mente infinidad de cosas, por ejemplo, datos de:
- Libros.
- Redes sociales.
- Casas y/o terrenos.
- Productos e-commerce.
- Pagos por Internet.
- Dinero y/o criptomonedas.
Los ejemplos anteriores son unos cuántos de la infinidad de datos que existen en el Internet. Pero, ¿cómo obtenemos esos datos y los mostramos en nuestro WordPress?
La solución es: API REST externas.
¿Qué es una API REST?
Una API REST es una interfaz entre sistemas que utilizan peticiones HTTP para obtener y/o modificar datos, y hasta ejecutar funcionalidades específicas de la API REST.
Las respuestas de estas peticiones HTTP serán en formato JSON o XML, y podrás hacer lo que quieras con ellas con tu lenguaje de programación favorito.
Si no sabes qué son las peticiones HTTP, sigue éste enlace para saber más al respecto (las peticiones más comunes son:
GET
yPOST
).Gráficamente, así es como funciona una petición a una API REST:
Funcionamiento de petición a una API REST externa. La lógica de la imagen anterior se explica de la siguiente manera:
- El cliente quiere conocer los estados del país México.
- Hay que hacer una petición a la API REST de
/servicios/estados/
. - A la petición hay que adjuntarle un parámetro
{ "pais": "México" }
. - El parámetro funciona como filtro para obtener los estados de nuestro país.
- Al final, nosotros decidiremos qué hacer con los resultados de la petición.
La API REST de CoinMarketCap
Vamos a desarrollar un pequeño plugin que se conecte a la API de CoinMarketCap; es una web que te muestra los precios de todas las criptomonedas que hay en el mercado.
Lo que queremos hacer es obtener las últimas 5 criptomonedas más populares del mercado y mostrarlas en nuestra barra de administración de WordPress, justo así:
Últimas 5 criptomonedas de CoinMarketCap Deberás crear una cuenta en CointMarketCap siguiendo los pasos en su guía. Lo importante que necesitaremos será la API Key.
¿Qué límites tiene la API REST de CoinMarketCap?
Ten en cuenta que la cuenta básica de la API de CoinMarketCap tiene un límite de 333 créditos por día y hasta 10,000 llamadas al mes, cada crédito equivale a un request a la API.
La mayoría de APIs siguen este mismo método para evitar el abuso de peticiones por parte de bots automatizados.
Así que debes tener en cuenta cómo administras tus llamadas a la API para poder ahorrar costos a mediano y largo plazo. En este post te explico algunas buenas prácticas a seguir después de implementar una API REST externa en WordPress.
¿Qué es la HTTP API de WordPress?
WordPress contiene un conjunto de funciones que pertenecen a la HTTP API, y sirven para hacer peticiones HTTP a API REST ó cualquier otro servidor que retorne alguna respuesta. Así mismo, también contiene funciones para leer dichas respuestas.
Lo que aprendas a continuación, te servirá para tus plugins y temas WordPress que desarrolles en el futuro.
¿Cómo usar la HTTP API de WordPress?
¿No sabes cómo hacer un plugin WordPress? Lee mi post donde te explico lo que necesitas para poder desarrollarlos.
Entonces, te comentaba sobre unas funciones de WordPress para hacer peticiones a una API REST, una de ellas es wp_remote_request():
wp_remote_request( string $url, array $args );
Ésta acepta dos parámetros:
$url
(string) – La URL donde haremos nuestra petición.$args
(array) – Los argumentos de nuestra petición.
Endpoint y argumentos de la API REST
En nuestro caso, la URL de nuestra petición sería la siguiente:
https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest
Y también debemos especificar la API KEY generada por CoinMarketCap dentro de un header llamado
X-CMC_PRO_API_KEY
. Todos los headers deben de estar dentro de un arreglo con índiceheaders
(al mismo tiempoheaders
es un arreglo) así como se ve en el siguiente código:$api_endpoint = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'; $api_args = array( 'headers' => array( 'X-CMC_PRO_API_KEY' => 'TU API DE COINMARKETCAP' ) ); $queries = array( 'start' => 1, 'limit' => 5, 'convert' => 'MXN', );
Usaremos las tres variables anteriores para construir y hacer la llamada a la API:
$api_endpoint
– Este es en endpoint donde se hará la petición.$api_args
– Un arreglo que contiene la API KEY dentro de las cabeceras (headers). Si no especificas este valor, la API retornará un error.$queries
– Son los query strings que serán usados en el endpoint para modificar la respuesta de la API.
Puedes cambiar los valores de la variable
$queries
, por ejemplo, si quieres convertir aEUR
en vez deMXN
, simplemente especificasEUR
en el índiceconvert
del arreglo.Si quieres obtener 10 o más criptomonedas en vez de 5, solo cambia el valor del índice
limit
del arreglo.Visita la documentación de la API de CoinMarketCap para más información de los parámetros que aceptan sus URLs.
Adjunta los argumentos a la petición
También dijimos que acepta un segundo parámetro, los argumentos:
$args = array( 'method' => 'GET', );
¡Sorpresa! Tenemos que especificarle qué tipo de método HTTP usará nuestra petición, en este caso la documentación de la API nos dice que usemos
GET
para la petición.Con los códigos anteriores, tenemos este código:
$api_endpoint = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'; $api_args = array( 'method' => 'GET', 'headers' => array( 'X-CMC_PRO_API_KEY' => 'TU API DE COINMARKETCAP' ) ); $queries = array( 'start' => 1, 'limit' => 5, 'convert' => 'MXN', ); $api_endpoint = add_query_arg( $queries, $api_endpoint ); $response = wp_remote_request( $api_endpoint, $api_args );
Nota la función
add_query_arg()
, esta se dedica a adjuntar todos los valores existentes de la variable$queries
como query strings al endpoint que nosotros especifiquemos. El resultado de esa función será:https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?start=1&limit=5&convert=MXN
Y listo, ya estamos haciendo una petición a la API REST de CoinMarketCap.
¿Cómo obtener el resultado de la petición API REST?
Podemos asignar el resultado de la petición a una variable, en este caso, se la asignamos a la variable
$response;
y aquí viene otra de las funciones de la HTTP API de WordPress,wp_remote_retrieve_body()
:wp_remote_retrieve_body( array $response );
Y como ven, acepta un parámetro de tipo array, y ahí es justo donde vamos a poner nuestra variable
$response
, la cual contiene la respuesta de nuestra petición.Entonces, nuestro código sería:
$api_endpoint = add_query_arg( $queries, $api_endpoint ); $response = wp_remote_request( $api_endpoint, $api_args ); $cryptos = json_decode( wp_remote_retrieve_body( $response ), true );
¿En verdad funciona? Momento de probar
¡Sí funciona! Si mandamos a imprimir la variable
$cryptos
con la funciónvar_dump()
, veríamos lo siguiente:Muestra resultados de la API usando var_dump()
Convierte el resultado JSON a un arreglo (array)
Hasta aquí todo bien, pero ahora tenemos un problema, el resultado en sí está en formato JSON, y tenemos que convertirlo a un array para que PHP lo pueda leer correctamente; esto lo hacemos con la función
json_decode()
:json_decode( string $string, bool $assoc_array );
La cual acepta dos parámetros:
$string
(string) – El JSON string a decodificar.$assoc_array
(bool) – Si queremos que la decodificación sea un array o no.
Y lo implementamos en nuestro código; nota que el segundo parámetro de la función
json_decode()
estrue
:$response = wp_remote_request( $api_endpoint, $api_args ); $cryptos = json_decode( wp_remote_retrieve_body( $response ), true );
¡Bien! Nuestra variable
$cryptos
ya es unarray
.Prepara tu barra de administración
Pero si recuerdan, les dije que debíamos agregar las criptomonedas en nuestra barra de administración de WordPress. ¡No temas! Es totalmente sencillo.
Tenemos que usar el hook llamado
admin_bar_menu
, el cual nos permite agregar un nuevo menú en la barra de administración:add_action( 'admin_bar_menu', 'wp_cmkcap_add_admin_bar_menu', 999 );
El código anterior nos indica que ejecutará la función
wp_cmkcap_add_admin_bar_menu()
en el momento que el hookadmin_bar_menu
sea ejecutado.Crea el menú principal
Ten mucho en cuenta que la función acepta un parámetro (
$wp_admin_bar
) de tipoWP_Admin_Bar
, éste será muy importante, porque nos permitirá agregar nuestro menú:function wp_cmkcap_add_admin_bar_menu( $wp_admin_bar ) { // }
A continuación, agregamos nuestro título principal del menú:
$parent_node = array( 'id' => 'wp_cmkcap_admin_bar', 'title' => 'Cryptocurrencies', ); $wp_admin_bar->add_node( $parent_node );
Ten en cuenta el método
add_node()
, éste será el encargado de agregar nuestro menú a la barra de administración de WordPress. Y recuerda muy bien qué valor le estás poniendo al índiceid
de la variable$parent_node
.Agrega los títulos dentro del menú
¿Recuerdan que convertimos nuestra respuesta JSON a un array? Bien, pues ahora lo leemos con la función
foreach
de PHP:foreach ( $cryptos['data'] as $crypto_data ) { $price = number_format( $crypto_data['quote'][ $queries['convert'] ]['price'] ); $child_node = array( 'id' => 'cryptocurrency-' . $crypto_data['id'], 'title' => $crypto_data['name'] . ' / $' . $price . ' ' . $queries['convert'], 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); }
La variable
$cryptos
con índicedata
contendrá toda la información de la criptomoneda, entonces si queremos solo el nombre de la criptomoneda, tendríamos que llamar a la variable de la siguiente forma:$crypto_data['name'];
Puedes revisar qué información contiene
$crypto_data
en la imagen cuando hicimos elvar_dump()
.Y ahora, quiero que pongas atención en el valor del índice
title
dentro de la variable$child_node
:$child_node = array( 'id' => 'cryptocurrency-' . $crypto_data['id'], 'title' => $crypto_data['name'] . ' / $' . $price . ' ' . $queries['convert'], 'parent' => 'wp_cmkcap_admin_bar', );
En el índice
title
es donde pondremos el nombre de la criptomoneda concatenado con su precio en pesos mexicanos, para este ejemplo.Y el valor del índice
parent
tendrá que ser igual al valor del índiceid
que le pusiste en tu variable$parent_node
. Esto para que cada título de la criptomoneda se vaya agregando abajo del menú Cryptocurrencies.Con el código anterior unido, la función
wp_cmkcap_add_admin_bar_menu()
se vería de esta manera:function wp_cmkcap_add_admin_bar_menu( $wp_admin_bar ) { $parent_node = array( 'id' => 'wp_cmkcap_admin_bar', 'title' => 'Cryptocurrencies', ); $wp_admin_bar->add_node( $parent_node ); $api_endpoint = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'; $api_args = array( 'method' => 'GET', 'headers' => array( 'X-CMC_PRO_API_KEY' => 'TU API DE COINMARKETCAP' ) ); $queries = array( 'start' => 1, 'limit' => 5, 'convert' => 'MXN', ); $api_endpoint = add_query_arg( $queries, $api_endpoint ); $response = wp_remote_request( $api_endpoint, $api_args ); $cryptos = json_decode( wp_remote_retrieve_body( $response ), true ); foreach ( $cryptos['data'] as $crypto_data ) { $price = number_format( $crypto_data['quote'][ $queries['convert'] ]['price'] ); $child_node = array( 'id' => 'cryptocurrency-' . $crypto_data['id'], 'title' => $crypto_data['name'] . ' / $' . $price . ' ' . $queries['convert'], 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); } }
Posibles errores de la petición API REST
Es muy común que las API REST que estemos utilizando devuelvan varios tipos de errores. Un error tal vez ocurra porque:
- Te faltó especificar la API KEY para autenticar tu sesión.
- Un parámetro que mandaste a la API está mal escrito y no existe.
- El endpoint no existe.
- El servicio de la API REST está fuera de servicio (timeout).
Si uno de los errores anteriores u otros sucede, en este momento en que el código no tiene validaciones contra errores, te devolvería un error PHP. Y no queremos eso.
Validación del timeout
En el caso de un timeout por parte de la API REST, la función
wp_remote_request()
retornará una instancia de tipoWP_Error
como respuesta y la validamos con la funciónis_wp_error()
:$api_endpoint = add_query_arg( $queries, $api_endpoint ); $response = wp_remote_get( $api_endpoint, $api_args ); if ( is_wp_error( $response ) ) { $child_node = array( 'id' => 'internal-error', 'title' => 'Internal Error - Notify the administrator.', 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); return; }
El código anterior menciona que si la variable
$response
es una instancia deWP_Error
entonces agrega un mensaje de error adentro de nuestro menú:Muestra error en menú si respuesta es una instancia de WP_Error. Validaciones al código HTTP de la petición API REST
Ahora podemos agregar las validaciones a otros tipos de errores. Por ejemplo, si hubiésemos especificado el endpoint a una ruta que no existe, la API devolverá el siguiente resultado:
{ "statusCode": 404, "error": "Not Found", "message": "Not Found" }
Y este error cuando no especificamos la API KEY en la petición:
{ "status": { "timestamp": "2021-04-18T18:41:41.318Z", "error_code": 1002, "error_message": "API key missing.", "elapsed": 0, "credit_count": 0 } }
Aquí tenemos respuestas diferentes en ambos casos, el primer resultado es un código HTTP 404 y el segundo es un 401. Significa que tenemos que agregar validaciones de acuerdo al código HTTP devuelto.
Para obtener el código HTTP actual de la petición tenemos que usar la función
wp_remote_retrieve_response_code( $response )
para después usar la respuesta de esa función dentro de una condición:$http_code = wp_remote_retrieve_response_code( $response ); $cryptos = json_decode( wp_remote_retrieve_body( $response ), true ); if ( 200 !== $http_code ) { $message = 404 === $http_code ? $cryptos['message'] : $cryptos['status']['error_message']; $child_node = array( 'id' => 'api-error', 'title' => 'API Error: ' . $message, 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); return; }
El código anterior menciona que si el código HTTP es diferente al número 200 (equivalente a un resultado exitoso) entonces obtendrá los mensajes de error y los insertará dentro de nuestro menú.
¡Ojo! Aquí tenemos que agregar una validación ternaria (variable
$message
) para obtener el mensaje de error ya que el resultado del error 404 es muy diferente al del error 401. Ten en cuenta este tipo de situaciones para evitar futuros errores.Con las validaciones integradas, el menú se verá así cuando algún error suceda:
Muestra error cuando código HTTP es 404. Muestra error cuando código HTTP es 401. Resultado final
¡Listo! Hemos terminado, descarga el código completo y ejecútalo en tu WordPress y verás cómo funciona a la perfección, así es como se debería ver el código:
/* Plugin Name: WP CoinMarketCap Plugin URI: https://roelmagdaleno.com/ Description: Get the latest cryptocurrency data. Version: 2.0 Author: Roel Magdaleno Author URI: https://roelmagdaleno.com/ License: GPL2 License URI: https://www.gnu.org/licenses/gpl-2.0.html */ function wp_cmkcap_add_admin_bar_menu( $wp_admin_bar ) { $parent_node = array( 'id' => 'wp_cmkcap_admin_bar', 'title' => 'Cryptocurrencies', ); $wp_admin_bar->add_node( $parent_node ); $api_endpoint = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'; $api_args = array( 'headers' => array( 'X-CMC_PRO_API_KEY' => 'TU API DE COINMARKETCAP' ) ); $queries = array( 'start' => 1, 'limit' => 5, 'convert' => 'MXN', ); $api_endpoint = add_query_arg( $queries, $api_endpoint ); $response = wp_remote_get( $api_endpoint, $api_args ); if ( is_wp_error( $response ) ) { $child_node = array( 'id' => 'internal-error', 'title' => 'Internal Error - Notify the administrator.', 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); return; } $http_code = wp_remote_retrieve_response_code( $response ); $cryptos = json_decode( wp_remote_retrieve_body( $response ), true ); if ( 200 !== $http_code ) { $message = 404 === $http_code ? $cryptos['message'] : $cryptos['status']['error_message']; $child_node = array( 'id' => 'api-error', 'title' => 'API Error: ' . $message, 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); return; } foreach ( $cryptos['data'] as $crypto_data ) { $price = number_format( $crypto_data['quote'][ $queries['convert'] ]['price'] ); $child_node = array( 'id' => 'cryptocurrency-' . $crypto_data['id'], 'title' => $crypto_data['name'] . ' / $' . $price . ' ' . $queries['convert'], 'parent' => 'wp_cmkcap_admin_bar', ); $wp_admin_bar->add_node( $child_node ); } } add_action( 'admin_bar_menu', 'wp_cmkcap_add_admin_bar_menu', 999 );
Funciones de ayuda
Pero podríamos usar otra función para hacer nuestras peticiones en vez de
wp_remote_request()
, y sería la función wp_remote_get(), la cual acepta los mismos parámetros que la función que hemos usado anteriormente.Solo que le pasamos únicamente el primer parámetro, que es la URL de la API REST; el código quedaría de ésta forma:
$api_endpoint = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'; $api_args = array( 'headers' => array( 'X-CMC_PRO_API_KEY' => 'TU API DE COINMARKETCAP' ) ); $queries = array( 'start' => 1, 'limit' => 5, 'convert' => 'MXN', ); $api_endpoint = add_query_arg( $queries, $api_endpoint ); $response = wp_remote_get( $api_endpoint, $api_args ); $cryptos = json_decode( wp_remote_retrieve_body( $response ), true );
Nótese que hemos eliminado la variable
$args
, (donde le decíamos que íbamos a hacer una peticiónGET
) ya que ésta función es solamente para hacer peticionesHTTP GET
.Si tu API te pide una petición HTTP
POST
, entonces usarías la función wp_remote_post().Puntos a tomar en cuenta
Cada API REST es diferente, nos piden distintos parámetros y alguno de ellos nos podría pedir ciertos argumentos, como cabeceras HTTP, el tiempo de espera del servidor, si desea verificar el SSL, entre otros. Si llegases a usar un argumento, lo tendrías que especificar dentro de la variable
$args
, por ejemplo:$args = array( 'timeout' => 30, 'httpversion' => '1.1', 'sslverify' => false, 'body' => array( 'username' => 'avengers', 'password' => 'infinitywars', ), ); wp_remote_post( $api_url, $args );
Otro punto a tomar en cuenta es que algunas API REST necesitarán una API KEY para poder realizar nuestras peticiones exitosamente; tienes que revisar en la documentación de la API REST que estés usando, si necesitas una API KEY para empezar a utilizar su recurso.
De vez en cuando, las API REST podrían alentar un poco tu sitio, todo depende de qué tan rápida sea la respuesta de la API REST que estés utilizando. La solución a esto es que sólo hagas una única petición al momento de activar tu plugin y guardes el resultado de la petición en un valor en tu base de datos, y de ahi vas leyendo su valor, así te ahorras las llamadas que podrían arruinar tu sitio.
Recursos para API REST y WordPress
¿Te interesa seguir trabajando con API REST y WordPress? Aquí te dejo algunos recursos:
- Lista de APIs públicas.
- La HTTP API de WordPress.
- Insomnia. Un programa para hacer peticiones HTTP a API REST.
Si has llegado hasta aquí, ¡te felicito!
Ahora, te invito a que en los comentarios me expongas tus dudas que surgieron a lo largo del post ó las ideas que tienes sobre cómo implementar esto en algún plugin.
Si con éste tutorial has hecho un plugin parecido al que acabamos de desarrollar, comenta con un screenshot los resultados y explícanos de que se trata. 🙂
Changelog
18/04/2021
- El endpoint, de CoinMarketCap, de ejemplo inicial se cambió porque dejó de existir. Ahora se usa un nuevo endpoint que requiere API KEY. El lector debe registrarse y obtener una API KEY para continuar con la guía.
- Ahora se usa la función
add_query_arg()
para adjuntar los query strings al endpoint final. - Se agregó la sección de manejo de errores donde se valida ciertos errores de la API.
- El código final se almacena en Gist en vez de descargarlo en formato ZIP.