wordpress-plugins

Caché y Transients API

Optimiza el tiempo de carga y reduce el consumo de recursos. Utiliza la Transients API para almacenar resultados de consultas pesadas o llamadas a APIs con tiempo de expiración.

En el desarrollo profesional de plugins para WordPress, la optimización del rendimiento es una obligación. A medida que tus proyectos escalan, realizan consultas complejas a la base de datos o consumen APIs externas, el tiempo de respuesta del servidor se vuelve un factor crítico.

En este capítulo desmitificaremos el ecosistema de caché nativo. Aprenderás a diferenciar las capas de caché de página, de objetos y de navegador. Dominarás la Transients API para almacenar resultados pesados de forma temporal y descubrirás cómo implementar estrategias de invalidación precisas mediante código. Prepárate para llevar la eficiencia de tus desarrollos al siguiente nivel.

11.1 Diferencias de caché en WP

El ecosistema de WordPress es inherentemente dinámico: cada vez que un usuario solicita una página, el servidor debe cargar el núcleo, ejecutar decenas de plugins, interpretar el tema activo y realizar múltiples consultas a la base de datos para ensamblar el HTML final. Este proceso, aunque flexible, es costoso en términos de recursos y tiempo. Para mitigar esto, intervienen múltiples capas de caché.

Como desarrollador de plugins, es fundamental comprender dónde y cómo opera cada tipo de caché. Ignorar estas capas es una de las principales causas de "bugs" difíciles de rastrear, como contenido que no se actualiza, nonces de seguridad que caducan prematuramente o scripts que cargan versiones antiguas.

A continuación, analizaremos los principales tipos de caché que afectan a WordPress y cómo impactan en el desarrollo de plugins.

Arquitectura de capas de caché

Para visualizar el flujo de una petición y dónde actúa cada capa de caché, observa el siguiente esquema. Cuando una capa tiene éxito (un "hit"), la petición se devuelve inmediatamente, evitando que las capas inferiores se ejecuten.

TEXT
[Navegador del Usuario] ├─> 1. Caché de Navegador / CDN (Archivos estáticos) [Servidor Web] ├─> 2. Caché de Página (Varnish, Nginx, Plugins de caché) │ (Si hay "Hit", se devuelve el HTML y WP NO se ejecuta) v (Si hay "Miss", arranca WordPress) [PHP / WordPress] ├─> 3. Caché de Opcode (OPcache) ├─> 4. Caché de Objetos (Memcached, Redis, o nativa volátil) │ (Evita repetir cálculos pesados o consultas a la BD) v [Base de Datos MySQL/MariaDB]

1. Caché de Página (Page Caching)

La caché de página guarda el resultado final de la ejecución de WordPress, es decir, el HTML estático. Puede estar gestionada por el servidor (como Varnish o FastCGI Cache) o por plugins de WordPress (como WP Rocket o W3 Total Cache).

  • Cómo impacta a tu plugin: Si la página está en caché, WordPress no se carga. Ningún archivo de tu plugin se ejecuta, y ganchos como init, wp, o template_redirect son completamente ignorados para esa visita.
  • Consideraciones de desarrollo: Si tu plugin muestra contenido dinámico basado en el usuario (como un contador de visitas en tiempo real, un carrito de compras o un saludo personalizado), la caché de página mostrará el mismo contenido a todos. Para solucionarlo, debes usar cargas asíncronas mediante AJAX (visto en el Capítulo 9) o la REST API (visto en el Capítulo 13) para actualizar fragmentos del DOM después de que el HTML estático haya cargado.

2. Caché de Objetos (Object Caching)

A diferencia de la caché de página, la caché de objetos no almacena HTML, sino datos: resultados de consultas a la base de datos, arrays complejos o variables que requieren un alto coste de procesamiento. WordPress cuenta con la clase interna WP_Object_Cache.

Existen dos modalidades fundamentales que debes distinguir:

  • No persistente (Por defecto): WordPress almacena objetos en memoria solo durante el ciclo de vida de una única petición. Si llamas a get_post(10) tres veces en el mismo flujo de carga, WordPress solo consultará la base de datos la primera vez; las otras dos las sacará de la memoria RAM de esa petición. Al terminar la carga de la página, esta caché se destruye.
  • Persistente: Mediante el uso de Drop-ins (object-cache.php) y tecnologías como Redis o Memcached, la caché de objetos sobrevive entre diferentes peticiones y diferentes usuarios.
  • Consideraciones de desarrollo: Debes programar asumiendo que un entorno de producción tendrá una caché de objetos persistente. Profundizaremos en cómo interactuar con esta API en la sección 11.4, pero el concepto clave es que nunca debes dar por sentado que una consulta directa a la base de datos te devolverá datos frescos si hay una caché persistente de por medio.

3. Caché de Opcode (Opcode Caching)

PHP es un lenguaje interpretado. En cada petición, el código fuente en texto plano debe ser analizado, compilado a bytecode (Opcode) y luego ejecutado. La caché de Opcode (como Zend OPcache) almacena este código precompilado en la memoria compartida del servidor.

  • Impacto en el desarrollo: Generalmente es transparente para ti como desarrollador. El código se ejecuta más rápido. Sin embargo, en entornos de desarrollo muy agresivos, si modificas un archivo .php y recargas inmediatamente, podrías no ver los cambios si el OPcache no está configurado para revalidar los timestamps de los archivos a tiempo.

4. Caché de Navegador y Edge (CDN)

Esta caché ocurre fuera del servidor principal. Los navegadores web y las Redes de Entrega de Contenido (CDN) almacenan recursos estáticos como hojas de estilo (.css), scripts (.js), imágenes y fuentes tipográficas.

  • Cómo impacta a tu plugin: Si actualizas tu plugin e incluyes un nuevo archivo JavaScript, pero mantienes el mismo nombre de archivo, es muy probable que los usuarios sigan ejecutando la versión antigua que tienen guardada en sus navegadores.
  • Consideraciones de desarrollo: Para evitar esto, es obligatorio utilizar correctamente el parámetro de versión en las funciones de encolado (revisadas en el Capítulo 7).
PHP
// Práctica incorrecta: sin versión, o forzando la versión global de WP wp_enqueue_script( 'mi-plugin-script', plugin_dir_url( __FILE__ ) . 'assets/app.js', array(), null ); // Práctica correcta: usar la versión del plugin o el filemtime del archivo $version = filemtime( plugin_dir_path( __FILE__ ) . 'assets/app.js' ); wp_enqueue_script( 'mi-plugin-script', plugin_dir_url( __FILE__ ) . 'assets/app.js', array(), $version );

Tabla Comparativa para Desarrolladores

Para resumir, aquí tienes una tabla de referencia rápida sobre qué debes tener en cuenta según la capa en la que te encuentres operando:

Capa de CachéLo que almacenaRiesgo principal para el pluginSolución habitual
PáginaHTML estático de toda la URLLógica PHP ignorada, vistas estancadas para usuariosUsar AJAX/REST para partes dinámicas
ObjetosDatos y variables de PHPLectura de datos obsoletos en la BDUso correcto de invalidación de caché
NavegadorArchivos JS, CSS, imágenesErrores en la interfaz por JS/CSS antiguoVersionado dinámico en wp_enqueue_*
Base de DatosConsultas SQL crudas (MySQL)Rara vez problemático si usas la API de WPUsar $wpdb correctamente

11.2 Almacenamiento con Transients

Las consultas complejas a la base de datos y, especialmente, las peticiones a APIs de terceros (como procesar un feed externo o consultar un servicio en la nube) son cuellos de botella clásicos en el rendimiento. Para mitigar este problema, WordPress proporciona la Transients API, un método estandarizado para almacenar datos en caché acompañados de un tiempo de expiración.

En esencia, un transient (transitorio) es muy similar a una opción guardada mediante la Options API, pero con una diferencia vital: tiene fecha de caducidad.

¿Dónde se guardan los Transients?

El comportamiento de la Transients API es inteligente y se adapta al entorno del servidor donde esté instalado tu plugin:

  1. Sin caché de objetos persistente: Si el servidor es básico, WordPress guarda los transients directamente en la tabla wp_options de la base de datos. Creará dos registros por cada transient: uno para el valor en sí y otro para el timestamp de expiración.
  2. Con caché de objetos persistente: Si el servidor tiene configurado Memcached o Redis (y el correspondiente drop-in object-cache.php), WordPress no toca la base de datos. Almacenará los transients directamente en la memoria RAM ultrarrápida del servidor, delegando la gestión de la expiración al propio motor de caché.

La regla de oro: Nunca asumas que el Transient existe

Dado que los transients pueden ser almacenados en la memoria RAM y gestionados por sistemas como Redis, pueden desaparecer antes de su fecha de caducidad. Si el servidor necesita liberar memoria, expulsará los transients más antiguos.

Por lo tanto, tu código jamás debe depender de la existencia de un transient para funcionar; siempre debe estar preparado para regenerar los datos si la consulta al transient devuelve false.

TEXT
Flujo lógico correcto para un Transient: ¿Existe el Transient en caché? ┌─────┴─────┐ │ │ SÍ (Hit) NO (Miss / Caducado) │ │ │ v │ 1. Ejecutar tarea pesada (Consulta DB / API Externa) │ 2. Guardar el resultado con set_transient() │ │ v v [ Devolver los datos para su uso ]

Funciones principales de la API

La API se compone principalmente de tres funciones increíblemente sencillas de utilizar.

1. Leer un transient: get_transient()

Recibe el nombre del transient y devuelve su valor. Si el transient no existe o ya ha expirado, devuelve estrictamente el booleano false.

Nota de seguridad: Debido a que devuelve false cuando falla, no debes guardar valores booleanos false dentro de un transient, ya que te será imposible distinguir si el valor es realmente false o si el transient simplemente ha expirado. Si necesitas almacenar estados booleanos, utiliza enteros (1 o 0).

2. Guardar un transient: set_transient()

Guarda el valor. Acepta tres parámetros:

  • $transient (string): Nombre único de la clave (máximo 172 caracteres). Es vital usar prefijos únicos, igual que con las opciones.
  • $value (mixed): El dato a guardar. Puede ser un string, un array o un objeto (WordPress se encarga de serializarlo automáticamente).
  • $expiration (int): El tiempo de vida en segundos.

Constantes de tiempo en WordPress: Para evitar calcular los segundos mentalmente y hacer tu código más legible, WordPress incluye constantes globales que deberías utilizar siempre en el parámetro $expiration:

  • MINUTE_IN_SECONDS (60)
  • HOUR_IN_SECONDS (3600)
  • DAY_IN_SECONDS (86400)
  • WEEK_IN_SECONDS (604800)
  • MONTH_IN_SECONDS (2592000)
  • YEAR_IN_SECONDS (31536000)

3. Eliminar un transient: delete_transient()

Borra el transient manualmente antes de que expire. Útil cuando sabes que los datos originales han cambiado y necesitas forzar una actualización (por ejemplo, al guardar un post).

Implementación del Patrón Estándar

El uso correcto de los transients requiere agrupar la comprobación y la generación en un solo bloque lógico. A continuación, se muestra el patrón de diseño definitivo que debes aplicar en tus plugins:

PHP
function mi_plugin_obtener_datos_complejos() { // 1. Definimos el nombre de la clave (¡con prefijo!) $transient_key = 'mi_plugin_usuarios_activos'; // 2. Intentamos obtener el dato $datos = get_transient( $transient_key ); // 3. Comprobamos si falló (no existe o expiró) if ( false === $datos ) { // 4. [TAREA PESADA] El transient no existe. Generamos los datos. // Esto podría ser un loop de WP_Query, un procesamiento matemático o una API. $datos = mi_plugin_consultar_api_externa_lenta(); // 5. Guardamos el dato recién generado. // En este ejemplo, lo guardamos por 12 horas. set_transient( $transient_key, $datos, 12 * HOUR_IN_SECONDS ); } // 6. Retornamos los datos, sin importar si vinieron del transient o se acaban de generar. return $datos; }

Transients de Red (Multisite)

Si estás desarrollando para una red Multisite (WPMU) y necesitas que un transient esté disponible para toda la red (en lugar de solo para el sitio específico dentro de la red donde se solicitó), WordPress proporciona una variante de las funciones anteriores:

  • get_site_transient()
  • set_site_transient()
  • delete_site_transient()

Estas funciones operan exactamente igual, pero si no hay caché de objetos configurada, guardarán los datos en la tabla wp_sitemeta en lugar de wp_options.

11.3 Limpieza e invalidación

Existe una famosa cita en ingeniería de software atribuida a Phil Karlton: "Solo hay dos cosas difíciles en Ciencias de la Computación: la invalidación de caché y nombrar cosas". En el desarrollo de plugins para WordPress, esta afirmación cobra un sentido absoluto.

Dejar que la caché expire por tiempo (como vimos en la sección anterior con los Transients) es una estrategia pasiva. Sin embargo, si tu plugin muestra un listado de "Últimos productos" y el administrador publica uno nuevo, esperar 12 horas a que la caché expire ofrecerá una experiencia de usuario deficiente. Aquí es donde entra la invalidación activa.

La invalidación activa consiste en purgar la caché programáticamente en el momento exacto en que los datos subyacentes cambian, garantizando que los usuarios siempre vean la información fresca sin sacrificar el rendimiento general.

Invalidación basada en Eventos (Hooks)

La arquitectura basada en eventos de WordPress hace que la invalidación de caché sea predecible. Debes identificar qué acciones (Actions) modifican los datos que tienes cacheados y enganchar tus funciones de limpieza a esos puntos específicos.

Supongamos que tienes un transient llamado mi_plugin_lista_posts_destacados. Deberías borrar este transient cada vez que un post se guarde, se actualice o se elimine.

PHP
// Función encargada de purgar los transients específicos del plugin function mi_plugin_limpiar_cache_destacados( $post_id ) { // Evitar limpiezas innecesarias durante autoguardados if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // Borrar el transient delete_transient( 'mi_plugin_lista_posts_destacados' ); } // Enganchar la limpieza a las acciones que alteran el contenido add_action( 'save_post', 'mi_plugin_limpiar_cache_destacados' ); add_action( 'deleted_post', 'mi_plugin_limpiar_cache_destacados' );

El problema de la invalidación masiva (y la solución del Versionado)

A diferencia de las consultas SQL, la API de Transients no permite borrar múltiples registros usando comodines (no existe un delete_transient( 'mi_plugin_*' )). Si tu plugin genera cientos de transients dinámicos (por ejemplo, mi_plugin_usuario_1, mi_plugin_usuario_2, etc.), iterar sobre todos ellos para borrarlos es ineficiente y, en entornos con caché de objetos persistente, a menudo imposible sin conocer las claves exactas.

La solución profesional a este problema es el Versionado de Caché.

En lugar de borrar los transients uno por uno, agregas un número de versión global al nombre de la clave del transient. Cuando necesitas invalidar todos los transients de tu plugin a la vez, simplemente incrementas ese número de versión. Los transients antiguos quedarán huérfanos y el motor de caché los expulsará eventualmente cuando expiren o necesite liberar memoria.

TEXT
[Flujo de Versionado de Caché] 1. Opción global en BD: 'mi_plugin_cache_version' = "v1" 2. Clave generada: 'mi_plugin_datos_usuario_7_v1' 3. El administrador cambia una configuración global. 4. El plugin actualiza 'mi_plugin_cache_version' a "v2". 5. Siguiente petición busca: 'mi_plugin_datos_usuario_7_v2' -> (Miss!) 6. Se regenera la caché con los nuevos datos.

Implementación en código:

PHP
function mi_plugin_obtener_version_cache() { $version = get_option( 'mi_plugin_cache_version' ); if ( ! $version ) { $version = time(); // Usar un timestamp como versión inicial update_option( 'mi_plugin_cache_version', $version ); } return $version; } // Para usar al guardar/leer datos: $clave = 'mis_datos_' . mi_plugin_obtener_version_cache(); set_transient( $clave, $datos, DAY_IN_SECONDS ); // Para invalidar TODA la caché del plugin instantáneamente: function mi_plugin_invalidar_toda_la_cache() { update_option( 'mi_plugin_cache_version', time() ); }

Limpieza de la Caché de Página de Terceros

Si tu plugin modifica la interfaz visual del front-end (por ejemplo, actualiza un banner global desde tus opciones), limpiar los transients no será suficiente si el sitio utiliza un plugin de caché de página (WP Rocket, W3 Total Cache, LiteSpeed, etc.), ya que estos sirven HTML estático.

Los plugins de caché bien programados escuchan ganchos estándar como clean_post_cache o save_post para limpiar partes de su propia caché. Sin embargo, si tu plugin utiliza tablas personalizadas o configuraciones globales que no disparan estos ganchos nativos, tendrás que invocar la limpieza de página explícitamente.

Para mantener buenas prácticas, nunca asumas que un plugin de terceros está activo. Comprueba si su función de purga existe antes de llamarla:

PHP
function mi_plugin_purgar_cache_pagina() { // WP Rocket if ( function_exists( 'rocket_clean_domain' ) ) { rocket_clean_domain(); } // W3 Total Cache if ( function_exists( 'w3tc_flush_all' ) ) { w3tc_flush_all(); } // LiteSpeed Cache if ( defined( 'LSCWP_V' ) || defined( 'LSCWP_DIR' ) ) { do_action( 'litespeed_purge_all' ); } }

El peligro de wp_cache_flush()

Al trabajar con la caché de objetos (que detallaremos en la siguiente sección), existe una función central llamada wp_cache_flush(). Su propósito es vaciar completamente la memoria de la caché de objetos.

Advertencia estricta: Como desarrollador de plugins, **nunca debes llamar a wp_cache_flush() en un entorno de producción como respuesta a una acción del usuario (como guardar una configuración).

Hacerlo no solo borra la caché de tu plugin, sino la de todo el núcleo de WordPress, la de otros plugins y, en servidores compartidos mal configurados (donde Redis/Memcached no aísla por prefijos), podría borrar la caché de otros sitios web alojados en el mismo servidor. El resultado es un pico masivo de CPU y consultas a la base de datos (conocido como Cache Stampede o estampida de caché) que puede tumbar el servidor instantáneamente. Utiliza siempre borrados selectivos o la técnica de versionado.

11.4 Object Cache a nivel de código

La API de Caché de Objetos (Object Cache API) es el motor interno que sustenta gran parte del rendimiento de WordPress. A diferencia de los Transients, que están diseñados para persistir por defecto (ya sea en la base de datos o en memoria), el Object Cache nativo es, en su estado puro, un sistema de almacenamiento en memoria RAM no persistente. Esto significa que los datos viven únicamente durante el ciclo de vida de la petición HTTP actual y se destruyen inmediatamente después de que el script PHP termina su ejecución.

Sin embargo, si el servidor cuenta con un sistema de caché persistente (como Redis o Memcached) y su respectivo archivo drop-in object-cache.php en el directorio /wp-content/, las mismas funciones de esta API pasan automáticamente a almacenar los datos de forma permanente entre peticiones. Tu código como desarrollador de plugins debe escribirse pensando en que el entorno puede cambiar de no persistente a persistente sin previo aviso.

Funciones fundamentales de la API

A nivel de código, interactuamos con la API mediante cuatro funciones principales. Todas ellas comparten una estructura jerárquica basada en una clave ($key) y un grupo ($group).

1. wp_cache_set() y wp_cache_add()

Ambas funciones guardan datos en la memoria, pero su comportamiento ante datos preexistentes es crucialmente distinto:

  • wp_cache_set( $key, $value, $group = '', $expire = 0 ): Guarda el valor sin importar si la clave ya existe. Si ya existía, sobrescribe el valor anterior.
  • wp_cache_add( $key, $value, $group = '', $expire = 0 ): Solo guarda el valor si la clave no existe previamente. Si la clave ya existe, la función devuelve false y no modifica nada. Es ideal para evitar condiciones de carrera (race conditions).

Nota sobre $expire: Al igual que con los transients, se mide en segundos. Si no se utiliza un sistema de caché persistente de terceros, este parámetro se ignora por completo, ya que la memoria se vacía al terminar la petición.

2. wp_cache_get()

wp_cache_get( $key, $group = '', $force = false, &$found = null ): Recupera el valor almacenado bajo esa clave y grupo.

3. wp_cache_delete()

wp_cache_delete( $key, $group = '' ): Elimina de forma inmediata el objeto de la memoria.

El concepto de "Grupos" de Caché

El parámetro $group te permite compartimentar la caché de tu plugin. Evita colisiones de nombres con el núcleo de WordPress o con otros plugins. En lugar de crear una clave kilométrica como mi_plugin_perfil_usuario_42, puedes estructurarlo limpiamente:

PHP
// Clave: 42, Grupo: mi_plugin_usuarios wp_cache_set( 42, $datos_usuario, 'mi_plugin_usuarios' );

Además, algunos motores de caché persistente como Memcached o Redis aprovechan los grupos para permitir la invalidación o flushing selectivo de un grupo entero, optimizando masivamente la limpieza.

El patrón de verificación estricto: El parámetro $found

Un error crítico y muy común en desarrolladores intermedios es verificar la existencia de un objeto en caché evaluando directamente si el resultado de wp_cache_get() es equivalente a false:

PHP
// PRÁCTICA INCORRECTA $resultado = wp_cache_get( 'estado_licencia', 'mi_plugin_grupo' ); if ( false === $resultado ) { // ¿La caché expiró o es que el estado real de la licencia es (bool) false? }

Si el resultado legítimo de una consulta pesada a la base de datos o a una API es el valor booleano false, un string vacío "" o el entero 0, la comprobación tradicional fallará catastróficamente, obligando a tu plugin a repetir la tarea pesada en cada petición.

Para solucionar esto, WordPress introdujo el cuarto parámetro por referencia llamado $found. Este parámetro se pasará a true si la clave existe en la caché (incluso si su valor es false o null), y a false si realmente hubo un cache miss.

Implementación Profesional del Object Cache

A continuación, se detalla la estructura exacta que debes implementar para envolver operaciones costosas mediante Object Cache utilizando el parámetro $found:

PHP
function mi_plugin_obtener_metricas_avanzadas( $usuario_id ) { $cache_key = 'metricas_' . $usuario_id; $cache_group = 'mi_plugin_informes'; $found = false; // Variable que pasaremos por referencia // Intentamos recuperar el valor y verificar su existencia real $metricas = wp_cache_get( $cache_key, $cache_group, false, $found ); // Si $found es verdadero, la caché existe (Hit). Lo devolvemos directamente. if ( $found ) { return $metricas; } // Si llegamos aquí, es un Cache Miss. Ejecutamos la lógica pesada. $metricas = mi_plugin_calculo_estructural_pesado( $usuario_id ); // Guardamos el resultado en la caché de objetos (expira en 1 hora si es persistente) wp_cache_set( $cache_key, $metricas, $cache_group, HOUR_IN_SECONDS ); return $metricas; }

Cuándo usar Transients vs. Object Cache

Para cerrar la arquitectura de rendimiento de tu plugin, debes memorizar esta distinción técnica:

TEXT
¿Los datos deben sobrevivir de forma GARANTIZADA entre peticiones? ├── SÍ ──> ¿Son datos específicos de un usuario o dinámicos? ──> TRANSIENTS API └── NO ──> ¿Solo los necesitas durante la carga actual? ───────> OBJECT CACHE API
  • Usa Transients: Cuando consultes una API externa (como el tiempo meteorológico, cotizaciones, o validación de licencias remota) y necesites que el dato persista por horas de manera garantizada, incluso en el hosting compartido más económico sin Redis.
  • Usa Object Cache: Cuando realices consultas SQL personalizadas con $wpdb dentro del código de tu plugin que puedan repetirse múltiples veces en la misma petición, o para almacenar estructuras de datos en memoria que se beneficien drásticamente si el cliente cuenta con un entorno de alto rendimiento basado en Redis/Memcached.

Resumen del capítulo

En este capítulo hemos dominado las capas de optimización y gestión del rendimiento en el desarrollo de plugins profesionales para WordPress:

  1. Diferencias de caché en WP: Aprendimos a mapear el ciclo de vida de una petición HTTP y cómo interactúan la caché de página (que bloquea la ejecución de PHP), la caché de objetos (interna de datos), el OPcache (precompilación de scripts) y el versionado de archivos estáticos en el navegador.
  2. Almacenamiento con Transients: Estudiamos la Transients API como mecanismo de persistencia temporal activa, comprendiendo su almacenamiento adaptativo (tabla wp_options o RAM) y el patrón correcto de rescate ante un cache miss.
  3. Limpieza e invalidación: Analizamos las estrategias para mantener la integridad de los datos mediante la purga reactiva ligada a hooks, los peligros globales de wp_cache_flush() y la técnica avanzada de versionado de claves de caché para invalidaciones masivas instantáneas.
  4. Object Cache a nivel de código: Desgranamos la API interna WP_Object_Cache, el uso estratégico de los grupos de caché y el patrón de desarrollo imperativo empleando el parámetro de comprobación estricta $found por referencia.

© 2026 Esdocu. Contenido bajo licencia MIT.

Editar esta página