Blog

  • Consejos para API REST externas en WordPress

    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.
    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.
    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:

    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.
    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 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 archivo functions.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ón wp_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 aprieta CTRL+R o click en el botón de play.

    Resultado de la función home_url() en Tinkerwell.
    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".
    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.
    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.
    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.
    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 es do_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.
    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 es localhost; 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.

  • Excluir métodos y tipos de pagos en MercadoPago

    Excluir métodos y tipos de pagos en MercadoPago

    Dentro de tu carrito de compras tienes integrado preferencias de MercadoPago para el manejo de todas las compras de tus usuarios con cualquier método o tipo de pago.

    Sin embargo, tú o tu jefe, deciden agregar un nuevo requerimiento al carrito de compras. Ahora necesitan excluir los métodos o tipos de pagos de todas las nuevas preferencias de MercadoPago.

    Digamos que el requerimiento dice que los pagos en efectivo con OXXO y las transferencias SPEI sean excluidos de las nuevas preferencias de MercadoPago.

    ¿Es posible? Claro que sí.

    En este tutorial te mostraré cómo excluir los métodos y tipos de pagos de las preferencias de MercadoPago.

    Antes de empezar necesitamos claves de integración

    Para seguir con las siguientes secciones, necesitas una Public Key y un Access Token, los cuales consigues creando una integración en MercadoPago.

    Aquí hay una guía de MercadoPago que te enseña a crear una integración.

    Obtener los métodos de pago de MercadoPago

    Para excluir uno o más métodos de pago en MercadoPago primero debemos conocer los ids de esos métodos de pago.

    Para obtener esos ids debemos hacer una petición GET al siguiente enlace:

    https://api.mercadopago.com/v1/payment_methods?public_key=[PUBLIC_KEY]

    Si te fijas bien, la URL acepta el parámetro public_key. Sirve para autenticar la petición. La public_key lo obtienes en tu panel de desarrollador de MercadoPago.

    Cuando ejecutas la petición debes recibir un JSON de respuesta con múltiples valores.

    [
        {
            "id": "debvisa",
            "name": "Visa Débito",
            "payment_type_id": "debit_card",
            "status": "active",
            "secure_thumbnail": "https://www.mercadopago.com/org-img/MP3/API/logos/debvisa.gif",
            "thumbnail": "http://img.mlstatic.com/org-img/MP3/API/logos/debvisa.gif",
            "deferred_capture": "unsupported",
            "settings": [
                {
                    "card_number": {
                        "validation": "standard",
                        "length": 16
                    },
                    "bin": {
                        "pattern": "^(400064|400443|400819|400889|401531|401863|401906|402708|402766|403130|404313|404597|405063|405689|405930|406285|407848|408340|408341|408343|408400|409851|410128|410177|410277|410881|410894|411117|411608|411673|411773|411775|411808|412294|412408|413098|415231|416916|418914|418928|419334|419335|419821|419822|419823|420767|420807|420831|420839|421003|421316|422299|422671|425983|425984|426188|426808|427088|428464|430967|432049|433126|433194|433454|434256|434257|434258|434769|434798|435769|436618|438099|441312|441313|441545|441549|442177|442192|442742|442756|442788|443042|443045|444888|444889|445016|445017|445319|446115|446116|446117|446118|446878|446985|446986|449187|449700|451312|455509|455510|455511|455533|455537|457249|457476|459497|460068|460700|460766|461046|465345|465495|465496|465497|465498|465762|465828|465829|466188|466397|467010|467596|469495|469693|470132|470502|471239|471724|473622|473702|473703|473993|474174|474176|474472|474477|474478|474646|476588|476840|476890|477177|477261|477961|478200|479303|480062|480076|480078|480922|481516|481517|481582|481588|481689|482473|483030|483104|483112|483314|483316|485043|485044|486742|486796|490070|490256|490950|491089|491282|491365|491566|491567|491580|492143|498587|498590|41891410|41891431|41892810|46227850|47658885|49156630|49156634|49156644|49156650|49156651|49156652|49156653|49156654|49156655|49156656|49156657|49156658|49156659|49156660|49156661|49156662|49156663|49156664|49156665|49156666|49156667|49156668|49156669|49156670|49156671|49156672|49156673|49156674|49156675|49156676|49156677|49156678|49156679|49156680|49156681|49156682|49156683|49156684|49156685|49156686|49156687|49156688|49156689|49156690|49156691|49156692|49156693|49156694|49156695|49156696|49156697|49156698|49156699)",
                        "installments_pattern": "",
                        "exclusion_pattern": "^(49156649|49156648|49156647|49156646|49156645|49156644|49156643|49156642|49156641|49156640|49156639|49156638|49156637|49156636|49156635|49156634|49156633|49156632|49156631|49156630|49156629|49156628|49156627|49156626|49156625|49156624|49156623|49156622|49156621|49156620|49156619|49156618|49156617|49156616|49156615|49156614|49156613|49156612|49156611|49156610|49156609|49156608|49156607|49156606|49156605|49156604|49156603|49156602|49156601|49156600)"
                    },
                    "security_code": {
                        "length": 3,
                        "card_location": "back",
                        "mode": "mandatory"
                    }
                }
            ],
            "additional_info_needed": [
                "cardholder_name"
            ],
            "min_allowed_amount": 5,
            "max_allowed_amount": 300000,
            "accreditation_time": 2880,
            "financial_institutions": [],
            "processing_modes": [
                "aggregator"
            ]
        }
    ]

    Con el JSON anterior encontrarás información de los métodos de pago. Para México se muestran los siguientes:

    • Visa Débito – debvisa
    • Mastercard Débito – debmaster
    • American Express – amex
    • Visa – visa
    • Mastercard – master
    • Citibanamex – banamex
    • OXXO – oxxo
    • BBVA Bancomer – bancomer

    Obtener los tipos de pago de MercadoPago

    Los tipos de pago sirven para identificar si queremos hacer cobros con tarjeta de débito/crédito, efectivo, tarjeta de prepago, entre otros.

    Estos tipos de pago son encontrados dentro de la misma respuesta JSON que obtuviste en la petición anterior. Específicamente, la propiedad payment_type_id.

    Estos son los tipos de pago y sus ids encontrados en la petición:

    • ATM – atm
    • Tarjeta de crédito – credit_card
    • Tarjeta de débito – debit_card
    • Ticket – ticket
    • Transferencia bancaria – bank_transfer

    Excluir métodos o tipos de pago de una preferencia de MercadoPago

    La siguiente sección solo funciona con preferencias de MercadoPago.

    Para crear una preferencia de MercadoPago usando su API, debemos seguir la documentación.

    La petición que haremos será de tipo POST al siguiente enlace:

    https://api.mercadopago.com/checkout/preferences

    Debemos estar autenticados con nuestro Bearer Token pasándole un header de autenticación:

    Y debemos pasar datos obligatorios para crear la preferencia.

    Dentro de la documentación, busca la propiedad payment_methods, la cual es una propiedad para excluir métodos o tipos de pago y también para poner un método de pago por default.

    La propiedad payment_methods acepta las propiedades excluded_payment_methods y excluded_payment_types. Estos son arreglos y dentro de estos irán objetos con los ids de los métodos y tipos de pago, respectivamente.

    Si estamos creando una preferencia y estamos excluyendo los métodos de pago oxxo y bancomer y los tipos de pago bank_transfer. El JSON a pasar a la petición debe verse de esta forma:

    {
      "items": [
        {
          "title": "Dummy Product",
          "description": "Dummy product description",
          "category_id": "car_electronics",
          "quantity": 1,
          "unit_price": 10
        }
      ],
      "payment_methods": {
        "excluded_payment_methods": [
          {
            "id": "oxxo"
          },
          {
            "id": "bancomer"
          }
        ],
        "excluded_payment_types": [
          {
            "id": "bank_transfer"
          }
        ]
      }
    }

    Recuerda que los ids de los métodos y tipos de pago se consiguieron anteriormente.

    El resultado del POST anterior será un JSON y te mostrará la información de la preferencia.

    Métodos y tipos de pago excluidos de la preferencia de MercadoPago

    Una vez creada la preferencia, la respuesta JSON tendrá las propiedades init_point y sandbox_init_point. Estos son los enlaces para enviar a tus clientes y puedan comprar.

    La propiedad sandbox_init_point es para pruebas. Entonces, si vamos a este enlace:

    https://sandbox.mercadopago.com.mx/checkout/v1/redirect?pref_id=703458213-0e171ffb-125f-4d27-9611-ae36e57e85cd

    Primero verás que no sale la opción “Transferencia SPEI”. Y si seleccionas “Efectivo”, en la siguiente ventana la opción para pagar con OXXO no estará.

    Y así es como excluyes métodos y tipos de pago en MercadoPago.

    Si tienes problemas o dudas, no dudes en comentar.

  • Agrega el botón “Empezar” en tu Messenger Bot

    Agrega el botón “Empezar” en tu Messenger Bot

    Hace un año empecé a leer sobre cómo desarrollar un Messenger Bot de Facebook; claro, sin ver nada de inteligencia artificial y esas cosas, algo sencillo.

    (más…)
  • Envía peticiones AJAX antes de cerrar la página web

    Envía peticiones AJAX antes de cerrar la página web

    Actualmente desarrollo plugins para WordPress, y recién me topé con algo que nunca había pensado: “Enviar peticiones AJAX antes de que el usuario cierre nuestra página web“.

    Antes de empezar este post, dejemos claro dos cosas:

    1. Lo que veremos a continuación será completamente JavaScript.
    2. El problema anterior puede ser enfocado a cualquier tipo de aplicación web, no solo para WordPress.

    Indagué por la web

    La mayoría de las respuestas a mi problema provenían de StackOverflow, y mi sorpresa fue que, no soy el único buscando lo mismo.

    Hasta hace unos años, varias personas recomendaban usar el siguiente método:

    • Realizar peticiones síncronas.

    El problema es que esto provoca que el navegador o la pestaña tarden un poco en cerrar, debido a que la petición aún se sigue ejecutando.

    Sin embargo, en años más recientes, hubo una persona que comentó dos palabras:

    Beacon API

    ¡Ésta es la solución! Me dije.

    ¿Por qué? Pues, se veía sencillo de usar y su documentación decía lo que yo quería hacer en ese momento. Y lo logré.

    Un resumen de lo que dice su documentación:

    La Beacon API es usada para realizar peticiones asíncronas y no bloqueables a un servidor web. Aborda las necesidades de ejecutar código que intenta enviar datos al servidor web antes de que el documento se cierre.

    La documentación lo explica sencillo, y el código mucho más; pero antes de seguir, me gustaría explicar que es una petición AJAX.

    ¿Qué es una petición AJAX?

    Al principio de mi carrera, el hacer uso de algo llamado AJAX en mis desarrollos, era algo tenebroso. Tal vez para ti, mi querido lector, también lo fue.

    ¡No le tengas miedo! De hecho, creo que fue una de las mejores cosas que pude haber conocido, y lo mejor que le pasó a la web.

    AJAX significa JavaScript Asíncrono y XML, y nos sirve prácticamente para:

    • Obtener datos de un servidor web sin recargar la página.
    • Enviar datos a nuestro servidor sin que el usuario se vea interrumpido.

    Hacer uso de AJAX hoy en día es totalmente normal, y lo puedes implementar con varias tecnologías, ya sea usando VanillaJS, jQuery u otros.

    A continuación, te dejo un video de Platzi para una mejor comprensión del tema:

    ¿Qué es AJAX y cómo funciona? – Por Platzi

    Compatibilidad

    Antes de empezar a trabajar con la Beacon API, hay que tener en cuenta que, en este año 2018, esta API es compatible en la mayoría de los navegadores, a excepción de Internet Explorer y Opera Mini:

    Compatibilidad de la Beacon API
    Imagen 1. Compatibilidad de la Beacon API entre navegadores.

    Usando la Beacon API

    Pero volvemos al principio del problema:

    Enviar peticiones AJAX antes de que el usuario cierre nuestra página web.

    La Beacon API nos provee la siguiente función:

    navigator.sendBeacon( url, data );

    Esta función nos permite enviar los datos que queremos transmitir a nuestro servidor antes de cerrar nuestra página.

    Acepta dos parámetros:

    ParámetroDescripción
    urlÉsta será la URL a donde queremos transmitir los datos.
    dataEste es una variable que contendrá los datos a enviar en la petición.

    Cabe destacar que, el tipo de la variable a enviar debe ser:

    Cualquiera de éstos tipos es aceptable, escoge el que más te convenga. Sin embargo, en los siguientes ejemplos usaremos FormData.

    Ahora, la pregunta del millón, ¿cómo lo usamos para enviar datos antes de cerrar nuestra página web?

    Bien, tenemos que usar un evento de JavaScript llamado unload, éste se ejecuta justo antes de que la página sea cerrada o recargada:

    window.addEventListener( 'unload', sendData, false );

    Cuando la página sea cerrada, se ejecutará la función sendData:

    function sendData() {
       var formData     = new FormData();
       var currentTasks = getSomeTasks();
    
       if ( Object.keys( currentTasks ).length <= 1 ) {
          return;
       }
    
       formData.append( 'action', 'cronjob_task_system' );
       formData.append( 'currentTasks', JSON.stringify( currentTasks ) );
    
       navigator.sendBeacon( myObject.url, formData );
    }

    Primero, tenemos que hacer una instancia de FormData, ó cualquier tipo de variable que mencionamos anteriormente, y agregar los datos que queremos enviar a nuestro servidor.

    Puedes hacer cualquier operación antes de enviar los datos, por ejemplo, yo en el código digo que si mi variable currentTasks está vacío, no envíe nada al servidor.

    ¿Por qué mi código está en inglés? Chécalo en mi post sobre ¿por qué es necesario nombrar bien las cosas en programación?

    Ya que la lógica esté lista, pasamos los respectivos parámetros a navigator.sendBeacon( url, data ) y manejamos esos datos en nuestro servidor.

    Inconvenientes

    El uso de la Beacon API es impresionante, cumple con nuestros objetivos al querer enviar datos al servidor cuando la página se haya cerrado; sin embargo, existe un inconveniente.

    Si queremos implementar la Beacon API, dijimos que tenemos que ejecutarlo en el evento unload, ¿verdad?

    Sin embargo, este evento se ejecuta no sólo cuando la página es cerrada, si no que también se ejecuta cuando el usuario recarga la página, o cuando el usuario cambia de página dentro del mismo dominio.

    Tal vez sea un inconveniente o no, depende del tipo de proyecto que estés desarrollando.

    Posible solución a los inconvenientes

    Como dije, la Beacon API tendrá sus inconvenientes o no, dependiendo del tipo de proyecto que estés desarrollando, por ejemplo, si quieres enviar datos estadísticos de las partes donde navegan tus usuarios, éste método es perfecto.

    Pero si andas buscando algo que únicamente se ejecute al cerrar la página, tal vez tengas que usar algo parecido al Heartbeat API de WordPress, para que tu servidor se comunique si el usuario sigue en tu página o no.

    Conclusión

    La verdad es que, el uso de la Beacon API me ha salvado de implementar demasiado código en el proyecto que estaba desarrollando, y espero que te pueda servir a ti también.

    Sin embargo, el uso del evento unload, es algo que debe mejorarse para solucionar los inconvenientes que previamente mencionamos.

    ¿No te ha funcionado la implementación del código? Deja un comentario y con gusto te apoyo.

  • Reduce los parámetros de tus funciones

    Reduce los parámetros de tus funciones

    Estaba programando una función en JavaScript, y la tenía que mandar a llamar en otros archivos, sin embargo, me di cuenta que cada vez que llamaba a esa función, era difícil acordarme de los parámetros.

    Empezamos a programar sin saber las buenas prácticas, y así lo hacemos durante mucho tiempo, pensando que nuestro código es de calidad.

    Pero no te preocupes, es algo que le pasa hasta los programadores más avanzados.

    ¿Qué son los parámetros?

    Los parámetros, o también conocidos como argumentos, son los que están a la espera de obtener un valor desde donde se llame la función que las contiene.

    Sí, son esas palabras que van dentro de los paréntesis de una función:

    function myFunction( parameter1, parameter2, ... ) {}

    Pero entre lenguajes de programación, estos parámetros podrían no representarse de la misma manera.

    Tienes que verificar cómo lo hace tu lenguaje de programación favorito. 🙂

    El problema de usar muchos parámetros

    Les mencioné que hice mi función en JavaScript; pues así se veía:

    function WPB_startAjaxRequest( event, formData, formId, ajaxAction, currentTask, shouldGetData, extraData, callback ) {
       // My code...
    }

    Una función con 8 parámetros. ¡¿En qué estoy pensando?!

    En fin, no le hice caso a esa función, dejé que siguiera trabajando de esa forma, pero los problemas persistían:

    ¡Sigo sin acordarme del orden de los parámetros!

    Entonces, ¿la función de arriba qué está provocando?

    Para empezar:

    • Estoy usando las buenas prácticas de buen nombramiento, sin embargo, como mi función tiene más de 4 parámetros, no es para nada legible.
    • Es difícil recordar el tipo de dato que espera cada parámetro.
    • También es complicado recordar el orden de los mismos.

    Los puntos anteriores solo te quitarán tiempo, tiempo valioso que podrías usar para programar, y tu código no será de calidad.

    ¡No hagas lo que yo hice!

    Sólo usa 3 o 4 parámetros

    Un día estaba leyendo el libro JavaScript: The Good Parts, y encontré una buena práctica, ésta decía que usar más de 3 o 4 parámetros en una función era una mala práctica.

    Y la solución que presentaba el autor, era que si necesitabas usar más de 3 o 4 parámetros, éstos los pasaras a través de un objeto; es decir:

    var myParameters = {
       ajaxAction:  'whatever',
       callback:    'startMyCallback()',
       currentTask: 'delete_everything'
    };
    
    WPB_startAjaxRequest( event, myParameters );

    Tras aplicar ésta solución, mi función se había convertido en esto:

    function WPB_startAjaxRequest( event, ajaxParameters ) {
       console.log( ajaxParameters );
       console.log( ajaxParameters.ajaxAction );
    }

    Es más legible, ¿no crees? De 8 parámetros, ahora tenemos 2.

    Pero, ¡Ojo!, no porque yo esté usando JavaScript aquí, no significa que no funcione en otros lenguajes de programación. 😉

    ¿Qué ventajas obtienes?

    Darle este tipo de soluciones a tu código, representa un gran avance a tu código, estás escribiendo código de calidad.

    Además, te está aportando lo siguiente:

    • Código más legible.
    • El código se vuelve más corto.
    • Y ya no tenemos que acordarnos del orden de los parámetros.

    ¡Esto es lo que deberías estar haciendo en cada uno de tus desarrollos!

    Uno de tantos code smells

    El problema anterior es clasificado como un “code smell” (hediondez del código), y éste termino se refiere a que una parte del código tiene alguna deficiencia y que a la larga, ralentizará el sistema que estás desarrollando.

    ¿Quieres ver la cantidad de code smells que existen? Los puedes encontrar en este enlace.

    Si te pones a solucionar todos estos code smells, no solo estás “solucionando”, si no que estarás “refactorizando“, y te sentirás como el Refactor Man:

    Refactor Man

    El término “refactorización” no significa agregar código nuevo, se refiere a mejorar tu código, convertir ese código revuelto a código simple.

    Tras ver todo esto, ¿estás decidido a programar código de calidad?

    Referencias

  • Elige la mejor tipografía para programar

    Elige la mejor tipografía para programar

    Cuando estás aprendiendo a programar, solo piensas en aprender las sintaxis del lenguaje de programación, funciones, propiedades, etc, pero creo que nadie nunca ha pensado en escoger la tipografía correcta desde un principio.

    Y no digo que esté mal, si no que, nosotros los programadores, pasamos la mayor parte del tiempo leyendo código que escribiéndolo; por lo tanto, debemos tener una tipografía que sea completamente legible. Una tipografía que no nos canse la vista.

    Otro factor a tomar en cuenta al momento de programar, es el nombramiento, el cual te lo explico en este post.

    ¿Qué es una tipografía?

    También conocidas como las fuentes o tipos de letras que están instaladas dentro de nuestra computadora; claro, hablando a nivel de informática.

    Sabemos de ellas gracias a las herramientas de ofimática, como Microsoft Office Word, Google Docs, etc; y por lo regular, éstas herramientas solo contienen las tipografías por default del sistema operativo donde estemos.

    Sin embargo, podemos descargar e instalar tipografías de terceros en nuestra computadora, a continuación una lista de sitios web para descargar tipografías de cualquier tipo:

    ¿Cuál es la tipografía correcta?

    No cualquier tipografía debería utilizarse para programar. Las tipografías que deberías usar en tu editor de texto, deben:

    • Ser legibles.
    • Tener caracteres distinguibles. Por ejemplo: Que el 1 (uno) sea distinto que la l (ele). Tal vez aquí se vea igual, pero, ¿entiendes el punto, verdad?
    • Los caracteres deben tener buen espacio entre cada uno.
    • Tengan disponibles caracteres especiales, como “<>$&/?=”, etc. Esos caracteres que a veces necesitamos para realizar alguna comparación u operación.

    Mi recomendación

    He probado distintas tipografías a lo largo de mi carrera como programador, y las siguientes tipografías que les voy a mostrar me han ayudado mucho al momento de programar, y esas son:

    Inconsolata

    Ejemplo de Tipografía Inconsolata

    Ejemplo de código JavaScript usando Source Code Pro.

    Source Code Pro

    Source Code Pro

    Ejemplo de código JavaScript usando Source Code Pro.

    Hack

    Ejemplo de Tipografía Hack

    Ejemplo de código JavaScript usando Hack.

    Aparentemente se ven igual, pero no, hay ligeros cambios entre ciertas letras, por ejemplo, la letra “g”.

    Tu vista no se cansará si usas al menos una de esas tres tipografías que he mencionado.

    Conclusión

    Como dije anteriormente, los comentarios que aquí he expresado son de mi humilde opinión, no te estoy obligando a usarlas.

    Si tú programas con otro tipo de tipografía y te sientes a gusto con ella, quédate con ella; pero recuerda, el probar no cuesta nada.

    Y dime, ¿usas alguna otra fuente que no haya mencionado y estás orgulloso de ella? Compártela en los comentarios para que los demás podamos probarla. 🙂

  • El buen nombramiento en la programación

    El buen nombramiento en la programación

    Probablemente seas nuevo en el mundo de la programación y estés leyendo un libro, tutorial o guía sobre programación; desde ese momento, ¿qué es lo que haces? Estás leyendo en vez de estar escribiendo. Por lo tanto, es muy importante que el nombramiento de las cosas que otros programadores y tú escriban, estén bien escritas.

    Y cuando digo “cosas“, me refiero a tus variables, funciones, parámetros e incluso comentarios. Éstos deben ser legibles y dar a entender lo que está haciendo la variable o función, si no lo son, perderás mucho tiempo leyendo el código.

    Los programadores pasamos más tiempo leyendo código que escribiéndolo.

    El problema del mal nombramiento de las cosas

    Si el nombramiento de las cosas no son legibles y mucho menos entendibles, te podrás ver afectado a futuro. A continuación, te muestro los puntos que probablemente enfrentarás si no nombras bien las cosas.

    Tu código no:

    • Será legible.
    • Podrá ser entendido ni por ti, ni por otros programadores.
    • Será escalable; es decir, se te dificultará agregar y/o actualizar el código.

    Y la peor de todas, tal vez te tengas que ver obligado a cambiar todo el código.

    Escribe tu código en inglés

    ¿Inglés? ¡Estás loco Roel, no me llevo con eso!

    No estoy loco, solo que mayormente la documentación de las librerías y frameworks están escritas en inglés; pocas veces se encuentra en español.

    Además, nunca sabes quién leerá tu código.

    Por ejemplo: Estás en una empresa escribiendo tu código en español, pero el administrador del proyecto te dice que necesita que le envíes tu código a su amigo americano. ¡Huy, problemas!

    Le comentas la situación al administrador del proyecto, y lamentablemente te dice que escribas tu código en inglés. ¡Tristeza! Tienes que volver a escribir el código.

    ¿Ya ves? Tu código lo podría leer alguien en la India, Estados Unidos, Dinamarca, etc.

    No programes para ti, programa para los demás

    Te pongo un ejemplo; tu has escrito el siguiente código:

    <?php
    
    $stuff = array( 'lemon', 'apple', 'pineapple' );
    $x     = 'apple';
    
    echo $stuff[ $x ];

    Y lo tienes que enviar al administrador del proyecto para que revise tu código, él va leyendo las variables y se encuentra con la variable:

    $stuff, la cual contiene una colección de frutas. Bueno, su primer pregunta es, ¿por qué la variable $stuff no se llama $fruits? No concuerda con su contenido.

    Después se encuentra con la variable $x, la cual es igual a apple. ¿Es enserio? —Se pregunta. Él pensó que la variable $x contenía el valor de una coordenada en el eje X.

    Vamos a nombrar bien estas variables:

    <?php
    
    $fruits   = array( 'lemon', 'apple', 'pineapple' );
    $my_fruit = 'apple';
    
    echo $fruits[ $my_fruit ];

    ¿Ves que ahora es más fácil de entender a qué se refiere cada variable? Pero el chiste no es escribir de nuevo el código, eso solo te ha quitado tu valioso tiempo.

    Siempre escribe bien desde el principio.

    Tal vez estos ejemplos sean algo simples y muy ilógicos, pero creanme, me he encontrado con estos casos, y ustedes también lo harán y se frustrarán.

    Tus palabras deben ser claras, no uses abreviaciones

    Para que lo anterior funcione, debes evitar escribir abreviaciones y las palabras de las acciones de tus variables y métodos deben ser claras, legibles y entendibles.

    Por ejemplo, tenemos el siguiente código:

    <?php
    
    $cat = get_cat_info_by_name( 'products' );
    
    echo $cat;

    ¿A qué nos referimos con el código anterior? ¿Estamos hablando sobre obtener la información de una categoría, de un catálogo o de un gato (cat, en inglés)?

    Lo anterior produce confusión y frustración. ¿Qué estás pidiendo en realidad?

    Lo correcto sería:

    <?php
    
    $category = get_category_info_by_name( 'products' );
    
    echo $category;

    Ahora si que, si tu variable contiene autos, tu variable debe llamarse $cars. Si tu variable contiene tipos de coches, entonces debes llamar a tu variable: $cars_types.

    ¿Entiendes mi punto?

    Pero, tampoco te excedas en nombrar las cosas; es decir, trata de usar palabras cortas, siempre que puedas. Ejemplo:

    <?php
    
    $categories_filtered_by_created_date = get_categories_by_date('product');
    
    var_dump( $categories_filtered_by_created_date );

    Hemos usado una variable con una buena cantidad de caracteres; para ser sinceros, se hace un poco difícil de leer. La solución es usar alguna palabra corta:

    <?php
    
    $categories_by_date = get_categories_by_date('product');
    
    var_dump( $categories_by_date );

    ¿Ves que ahora la variable se lee claramente?

    Siempre trata de eliminar las palabras que agreguen complejidad a tu variable o función.

    El nombramiento de las funciones y la documentación

    La documentación es odiada por todos, yo la odio, pero es buena práctica escribirla, obviamente, clara y simple de entender, como lo hemos visto anteriormente.

    ¿Por qué? Tú puedes escribir tu código bien escrito, siguiendo las recomendaciones anteriores, pero, ¿qué pasa si quieres leer el código un año después que lo escribiste?

    ¡Así es! Probablemente no comprendas de qué se trate el código que escribiste, sin embargo, hay algunos casos en los que la documentación no es tan necesaria.

    Una documentación puede ser opcional siempre y cuando tu código explique por si solo lo que está haciendo; por ejemplo, y es aquí donde aplicamos el buen nombramiento de las funciones:

    Tenemos la función is_plugin_active() de WordPress, la cual sí tiene su propia documentación:

    Pero podría ser opcional, ya que el mismo nombre de la función explica lo que está haciendo.

    Sin embargo, está la función get_plugin_data(), cuya documentación abarca muchas líneas de código:

    ¿Notas la gran diferencia? Mientras más hagas entendibles tus códigos, menos documentación tendrás que escribir.

    La documentación te ayuda a ti y a los demás programadores a entender el código que se ha escrito.

    Conclusión

    La buena práctica de nombrar bien las cosas es algo muy importante que debes tomar en cuenta, te ayuda a ti mismo y ayuda a demás programadores a ser mejores programadores.

    Si mezclas esta buena práctica junto con el mejor manejo de tus condicionales, tu código será elegante y profesional.

    Espero que te lleves algo bueno de este post, y apliques los conocimientos en los códigos que hayas hecho o estés por hacer.

    Si tienes alguna duda, comentario ó sientes que me faltó algo, por favor, házmelo saber en los comentarios.

  • Domina el uso de tus condiciones en PHP

    Domina el uso de tus condiciones en PHP

    Conocemos las condiciones en PHP, pero ¿qué tan eficientes son las que tu escribes? Las condiciones pueden afectar la legibilidad de tu código e incluso afectar el rendimiento de tu aplicación.

    Los problemas en las condiciones

    He visto a desarrolladores nuevos en grupos de Facebook publicar su código, ¿y saben qué es lo que he notado? Problemas en sus condiciones:

    • No son para nada legibles ni eficientes, por lo tanto, son complejas.
    • Ejecutan condiciones de más, provocando el famoso callback hell.
    • No utilizan las condiciones Yoda (Esto puede ser opcional en cada desarrollador, pero yo lo recomiendo como buena práctica).

    Yo sufrí lo mismo; y es que cuando estás empezando a desarrollar en PHP, como que te cuesta encontrar una guía de buenas prácticas al momento de estar desarrollando.

    Yo encontré la guía PHP: The Right Way muy tarde, se los recomiendo.

    Nota: El código que verás en todo el post estará en inglés, ¿por qué? La respuesta te la cuento en este post sobre cómo debes nombrar tus variables apropiadamente.

    Tu código debe ser legible, no lo hagas más complejo

    Hay una verdad en los programadores:

    Los programadores pasamos la mayor parte de nuestro tiempo leyendo código que escribiéndolo.

    Por lo tanto, todo el código que nosotros escribamos, deberá ser legible para que tanto nosotros como otros programadores lo lean rápido y por ende, el código sea fácil de entender.

    ¿No queremos gastar nuestro tiempo tratando de adivinar lo que hace el código o si?

    Lo siguiente pasa muy seguido en los desarrolladores nuevos:

    <?php
    
    $animals = array(
       'dog',
       'cat',
       'elephant',
    );
    
    if( is_array( $animals ) ) {
       if( ! empty( $animals ) ) {
          do_something();
       }
    }

    ¿Si notas cómo el código de arriba se hace un poco difícil de leer? Entre más tedioso sea de leer, más complejo se volverá tu código.

    El código anterior es un ejemplo de condiciones anidadas. Ahora, ¿Qué ocurre cuando empiezas a anidar condición tras condición, función tras función?

    Ocurre el famoso callback hell; la siguiente imagen no contiene código PHP, pero es un ejemplo muy claro de un callback hell, condiciones tras condiciones (abre la imagen en una pestaña para verla mejor, si es que te atreves):

    Condiciones anidadas provocando callback hell

    ¿Pudiste descifrar lo que hace el código? ¡Yo ni me tomé el tiempo de leerlo! Tan sólo mira esa complejidad. Eso es lo que tratamos de evitar.

    La solución de nuestro código anterior sería usar los operadores lógicos, en este caso, el operador AND:

    <?php
    
    $animals = array(
       'dog',
       'cat',
       'elephant',
    );
    
    if( is_array( $animals ) && ! empty( $animals ) ) {
       do_something();
    }

    ¿Notas la diferencia? Es más legible y menos complejo. Los operadores lógicos están aquí para ayudarnos, así que pon atención a tus clases de Matemáticas Discretas (bueno, al menos yo lo vi en esa materia).

    Usa cláusulas de guardia

    Éste método funciona como un guardia que protege tu código, para poder llegar a la siguiente sección del código debes pasar ese guardia, y así sucesivamente.

    Gráficamente trabaja así:

    Clausulas de Guardia

    ¿Pero realmente de qué sirve? Nos aporta mayor legibilidad a nuestro código, nos ayuda a no ejecutar código de más y evita el callback hell.

    El siguiente ejemplo no tiene cláusulas de guardia:

    <?php
    
    function is_user_registered( $username ) {
       $usernames_list = array(
          'roelmagdaleno',
          'rokumetal',
          'elbuenprogramador117',
       );
    
       $user_data = array();
    
       if( in_array( $username, $usernames_list ) ) {
          $user_data = get_user_data( $username );
       }
    
       return $user_data;
    }

    La función anterior nos dice que si el usuario está registrado, nos retorne los datos del usuario que está tratando de iniciar sesión, en caso contrario, mandemos un array vacío.

    Ahora, mira la misma función pero usando las cláusulas de guardia:

    <?php
    
    function is_user_registered( $username ) {
       $usernames_list = array(
          'roelmagdaleno',
          'rokumetal',
          'elbuenprogramador117',
       );
    
       $user_data = array();
    
       if( ! in_array( $username, $usernames_list ) ) {
          return $user_data;
       }
    
       return get_user_data( $username );
    }

    ¿Ves como hemos negado la función in_array()? Le estamos diciendo que si el usuario no existe, retorna un array vacío, en cambio, si existe, continúa con el código y obtiene los datos del usuario.

    ¡Así es como funcionan las cláusulas de guardia! Tienes que pasar cada guardia para proseguir ejecutando el código.

    Otro ejemplo, pero ahora con condiciones anidadas:

    <?php
    
    function is_current_user_admin( $username ) {
       $usernames_list = array(
          'roelmagdaleno',
          'rokumetal',
          'elbuenprogramador117',
       );
    
       if( in_array( $username, $usernames_list ) ) {
          $user_data = get_user_data( $username );
    
          if( 'administrator' === $user_data['role'] ) {
             return true;
          }
       }
    
       return false;
    }

    La función anterior valida si el usuario actual que está tratando de iniciar sesión es un administrador o no. Pero, ¿si sientes que pierdes un poco de tiempo tratando de leer el código?

    Bien, entonces, la función anterior sería de la siguiente forma usando cláusulas de guardia:

    <?php
    
    function is_current_user_admin( $username ) {
       $usernames_list = array(
          'roelmagdaleno',
          'rokumetal',
          'elbuenprogramador117',
       );
    
       if( ! in_array( $username, $usernames_list ) ) {
          return 'The user does not exists.';
       }
    
       $user_data = get_user_data( $username );
    
       if( 'administrator' !== $user_data['role'] ) {
          return false;
       }
    
       return true;
    }

    ¡Estupendo! Eliminamos la condición anidada y ahora es más fácil de leer el código, y un extra fue que evitamos un posible callback hell.

    ¿Tienes funciones que contengan condiciones anidadas? Trata de convertirlas usando cláusulas de guardia y pega tus resultados en los comentarios.

    Evita usar “else” en tus condiciones

    ¿Enserio, no usar el else? Sí, hablo enserio.

    ¿No te ha pasado que cuando usas la palabra reservada else, se te dificulta leer más el código? Exacto.

    Esta declaración lo que hace es agregarle más complejidad a nuestro código y por ende, más difícil de leer. Por ejemplo, sé que puedes leer el siguiente código, pero ¿cuánto te tardas en entender lo que realmente hace?:

    <?php
    
    $username = $_POST['username'];
    $password = $_POST['password'];
    
    if( empty( $username ) || empty( $password ) ) {
       return 'user-login.php';
    } elseif( ! empty( $username ) && ! empty( $password ) && 'roelmagdaleno' === $verification_code ) {
       $sql = 'My SQL Query';
       // More code here...
    } else {
       echo 'Ups! Your verification code is wrong!';
    }
    

    Bueno, el código representa un inicio de sesión, pero volvemos a lo mismo: legibilidad y complejidad. Y todos hemos escrito código parecido al anterior, no me dejarán mentir.

    ¿Cómo podemos evitar el else? Aquí tenemos dos soluciones:

    Usar funciones para validar los datos y cláusulas de guardia; por lo tanto, el código anterior quedaría de la siguiente manera:

    <?php
    
    $username = $_POST['username'];
    $password = $_POST['password'];
    
    if ( empty( $username ) || empty( $password ) ) {
       return 'user-login.php';
    }
    
    if( ! validate_password_and_user_data( $username, $password, $verification_code ) ) {
       return 'Something is wrong with your data.';
    }
    
    return 'All good! Go to dashboard.';
    
    function validate_password_and_user_data( $username, $password, $verification_code ) {
       if( 'roelmagdaleno' !== $verification_code ) {
          return false;
       }
    
       $sql = 'My SQL query to get username data.';
    
       if( $password !== $sql['password'] ) {
          return false;
       }
    
       return true;
    }

    ¿Es más código? Sí, pero ésta solución hace que nuestros ojos no sangren al momento de ver el código, y no, no hemos usado ni un else.

    El operador ternario

    Vamos a usar un código directo, ¿has escrito un código como el siguiente?

    <?php
    
    $new_color = '';
    
    if( isset( $_POST['color'] ) ) {
       $new_color = $_POST['color'];
    } else {
       $new_color = 'red';
    }
    
    echo 'The current color is ' . $new_color;

    Lo que estamos haciendo en el código anterior es que si existe el valor de un color que es traído desde un formulario, lo asigne a la variable $new_color, pero, sino existe, asigna un color por default.

    El operador ternario puede reducir este tipo de condiciones con la siguiente sintaxis:

    condición ? valor_si_es_verdadero : valor_si_es_falso;

    Siguiendo la sintaxis anterior, nuestro código ahora sería:

    <?php
    
    $new_color = isset( $_POST['color'] ) ? $_POST['color'] : 'red';
    
    echo 'The current color is ' . $new_color;

    ¡Wow! Nos ahorramos 5 líneas de código.

    Una buena práctica que siempre hago es hacer primero la condición sin el operador ternario, y después, ya que he analizado bien mi condición, aplico el operador ternario.

    Si usas otro lenguaje de programación, busca en este enlace si es compatible, o puedes probar directo en tu código.

    Operador de fusión de null

    Y hay una característica mucho mejor, pero solo es a partir de PHP 7, y se llama: operador de fusión de null. Su sintaxis es:

    variable_a_verificar_si_existe ?? valor_por_default;

    Y nos sirve para verificar si una variable existe, y si existe y no es null, asigna ese valor a la variable, en caso contrario, asignará el valor por default. Por ejemplo:

    <?php
    
    $username = $_GET['username'] ?? 'John Doe';

    Si $_GET['username'] existe y no es null, entonces la variable $username será igual a $_GET['username'], en caso contrario, será igual a John Doe.

    Realmente, este operador hace una operación ternaria por detrás. El código anterior equivale a esta operación ternaria:

    <?php
    
    $username = isset( $_GET['username'] ) ? $_GET['username'] : 'John Doe';

    Recuerda, sólo funciona a partir de PHP 7 para arriba.

    Condiciones Yoda

    No explicaré aquí lo que es una condición Yoda, ya que he escrito un post específico para ese tema, y lo puedes leer en éste enlace.

    Aplica los conocimientos aprendidos

    Me da mucho gusto que hayas llegado hasta aquí, y espero que hayas aprendido algo, pero si te ha quedado alguna duda, tienes algún comentario ó sientes que me faltó una buena práctica, me gustaría que la compartieras en la caja de comentarios.

    También te invito a compartir esta guía de buenas prácticas para que más desarrolladores nuevos aprendan a desarrollar de manera legible y menos compleja.

    Y doy el agradecimiento a Carl Alexander por hacer su post del cual me he inspirado para escribir este.

  • Utiliza una API REST externa con WordPress

    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 y POST).

    Gráficamente, así es como funciona una petición a una API REST:

    Funcionamiento de petición a una API REST externa.
    Funcionamiento de petición a una API REST externa.

    La lógica de la imagen anterior se explica de la siguiente manera:

    1. El cliente quiere conocer los estados del país México.
    2. Hay que hacer una petición a la API REST de /servicios/estados/.
    3. A la petición hay que adjuntarle un parámetro { "pais": "México" }.
    4. El parámetro funciona como filtro para obtener los estados de nuestro país.
    5. 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?

    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 índice headers (al mismo tiempo headers 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 a EUR en vez de MXN, simplemente especificas EUR en el índice convert 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ón var_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() es true:

    $response = wp_remote_request( $api_endpoint, $api_args );
    $cryptos  = json_decode( wp_remote_retrieve_body( $response ), true );

    ¡Bien! Nuestra variable $cryptos ya es un array.

    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 hook admin_bar_menu sea ejecutado.

    Crea el menú principal

    Ten mucho en cuenta que la función acepta un parámetro ($wp_admin_bar) de tipo WP_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 índice id 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 índice data 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 el var_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 índice id 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 tipo WP_Error como respuesta y la validamos con la función is_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 de WP_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ón GET) ya que ésta función es solamente para hacer peticiones HTTP 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:

    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.