WordPress, de forma predeterminada, realiza una forma de "almacenamiento en caché de objetos", pero su vida útil es solo una carga de página.
Las opciones son realmente un buen ejemplo de esto. Mira esta respuesta para más información. El resumen:
- Comienza una página
- Todas las opciones se cargan con una
SELECT option_name, option_value from $wpdb->options
declaración simple
- Solicitudes posteriores para esas opciones (por ejemplo, una llamada para que
get_option
nunca llegue a la base de datos porque están almacenadas con la API de caché de WP.
Las opciones siempre "viven" en la base de datos y siempre se mantienen allí, esa es su fuente "canónica". Dicho esto, las opciones se cargan en el caché de objetos, por lo que cuando solicita una opción hay un 99% de posibilidades de que la solicitud nunca llegue a la base de datos.
Los transitorios son un poco diferentes.
WordPress le permite reemplazar la API de caché con un menú desplegable , un archivo que se coloca directamente en su wp-content
carpeta. Si crea su propia memoria caché o usa un complemento existente , puede hacer que la memoria caché del objeto persista más de una sola carga de página. Cuando haces eso, transitorios, cambian un poco.
Echemos un vistazo a la set_transient
función en wp-includes/option.php
.
<?php
/**
* Set/update the value of a transient.
*
* You do not need to serialize values. If the value needs to be serialized, then
* it will be serialized before it is set.
*
* @since 2.8.0
* @package WordPress
* @subpackage Transient
*
* @uses apply_filters() Calls 'pre_set_transient_$transient' hook to allow overwriting the
* transient value to be stored.
* @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success.
*
* @param string $transient Transient name. Expected to not be SQL-escaped.
* @param mixed $value Transient value. Expected to not be SQL-escaped.
* @param int $expiration Time until expiration in seconds, default 0
* @return bool False if value was not set and true if value was set.
*/
function set_transient( $transient, $value, $expiration = 0 ) {
global $_wp_using_ext_object_cache;
$value = apply_filters( 'pre_set_transient_' . $transient, $value );
if ( $_wp_using_ext_object_cache ) {
$result = wp_cache_set( $transient, $value, 'transient', $expiration );
} else {
$transient_timeout = '_transient_timeout_' . $transient;
$transient = '_transient_' . $transient;
if ( false === get_option( $transient ) ) {
$autoload = 'yes';
if ( $expiration ) {
$autoload = 'no';
add_option( $transient_timeout, time() + $expiration, '', 'no' );
}
$result = add_option( $transient, $value, '', $autoload );
} else {
if ( $expiration )
update_option( $transient_timeout, time() + $expiration );
$result = update_option( $transient, $value );
}
}
if ( $result ) {
do_action( 'set_transient_' . $transient );
do_action( 'setted_transient', $transient );
}
return $result;
}
Hmmm $_wp_using_ext_object_cache
? Si es cierto, WordPress usa el caché de objetos en lugar de la base de datos para almacenar transitorios. Entonces, ¿cómo se establece eso en verdad? Es hora de explorar cómo WP configura su propia API de caché.
Puede rastrear casi todo hasta wp-load.php
o wp-settings.php
, los cuales son cruciales para el proceso de arranque de WordPress. En nuestro caché, hay algunas líneas relevantes en wp-settings.php
.
// Start the WordPress object cache, or an external object cache if the drop-in is present.
wp_start_object_cache();
¿Recuerdas esa caída desde arriba? Vamos a echar un vistazo a wp_start_object_cache
en wp-includes/load.php
.
<?php
/**
* Starts the WordPress object cache.
*
* If an object-cache.php file exists in the wp-content directory,
* it uses that drop-in as an external object cache.
*
* @access private
* @since 3.0.0
*/
function wp_start_object_cache() {
global $_wp_using_ext_object_cache, $blog_id;
$first_init = false;
if ( ! function_exists( 'wp_cache_init' ) ) {
if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
require_once ( WP_CONTENT_DIR . '/object-cache.php' );
$_wp_using_ext_object_cache = true;
} else {
require_once ( ABSPATH . WPINC . '/cache.php' );
$_wp_using_ext_object_cache = false;
}
$first_init = true;
} else if ( !$_wp_using_ext_object_cache && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
// Sometimes advanced-cache.php can load object-cache.php before it is loaded here.
// This breaks the function_exists check above and can result in $_wp_using_ext_object_cache
// being set incorrectly. Double check if an external cache exists.
$_wp_using_ext_object_cache = true;
}
// If cache supports reset, reset instead of init if already initialized.
// Reset signals to the cache that global IDs have changed and it may need to update keys
// and cleanup caches.
if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) )
wp_cache_switch_to_blog( $blog_id );
else
wp_cache_init();
if ( function_exists( 'wp_cache_add_global_groups' ) ) {
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'site-transient', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache' ) );
wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
}
}
Las líneas relevantes de la función (las que pertenecen a $_wp_using_ext_object_cache
eso alteran la forma en que se almacenan los transitorios).
if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
require_once ( WP_CONTENT_DIR . '/object-cache.php' );
$_wp_using_ext_object_cache = true;
} else {
require_once ( ABSPATH . WPINC . '/cache.php' );
$_wp_using_ext_object_cache = false;
}
si object-cache.php
existe en su directorio de contenido, se incluye y WP asume que está utilizando un caché externo y persistente; se establece $_wp_using_ext_object_cache
en verdadero.
Si está utilizando un objeto externo, los transeúntes lo usarán. Lo que plantea la cuestión de cuándo usar las opciones frente a los transitorios.
Simple. Si necesita datos para persistir indefinidamente, use las opciones. Se "almacenan en caché", pero sus fuentes canónicas son la base de datos y nunca desaparecerán a menos que un usuario lo solicite explícitamente.
Para los datos que deben almacenarse durante un período de tiempo establecido, pero que no necesitan persistir más allá de una vida útil específica, utilice transitorios. Internamente, WP intentará usar un caché de objetos externo y persistente si puede, de lo contrario, los datos irán a la tabla de opciones y se recolectará la basura a través de psuedo-cron de WordPress cuando caduquen.
Algunas otras preocupaciones / preguntas:
- ¿Está bien hacer un montón de llamadas
get_option
? Probablemente. Incurren en la llamada a una sobrecarga de la función, pero es probable que no llegue a la base de datos. La carga de la base de datos suele ser una preocupación mayor en la escalabilidad de las aplicaciones web que el trabajo que el idioma de su elección genera al generar una página.
- ¿Cómo sé usar transitorios frente a la API de caché? Si espera que los datos persistan durante un período determinado, use la API transitoria. Si no importa si los datos persisten (por ejemplo, no toma mucho tiempo calcular / recuperar los datos, pero no debería suceder más de una vez por carga de página) use la API de caché.
- ¿Todas las opciones están realmente en caché en cada carga de página? No necesariamente. Si llama
add_option
con su último argumento opcional, ya no
que no se cargan automáticamente. Dicho esto, una vez que los recuperas una vez, van al caché y las llamadas posteriores no afectarán la base de datos.