O WordPress, por padrão, faz uma forma de "Cache de Objeto", mas sua vida útil é apenas um carregamento de página única.
As opções são realmente um bom exemplo disso. Confira esta resposta para mais informações. O sumário:
- Uma página começa
- Todas as opções são carregadas com uma
SELECT option_name, option_value from $wpdb->options
declaração simples
- Solicitações subsequentes para essas opções (por exemplo, uma chamada para
get_option
nunca atingir o banco de dados porque elas são armazenadas com a API de cache do WP.
As opções sempre "vivem" no banco de dados e sempre persistem lá - essa é a fonte "canônica". Dito isso, as opções são carregadas no cache do objeto; portanto, quando você solicita uma opção, há 99% de chance de a solicitação nunca atingir o banco de dados.
Os transientes são um pouco diferentes.
O WordPress permite que você substitua a API do cache por um drop-in - um arquivo que é colocado diretamente na sua wp-content
pasta. Se você criar seu próprio cache ou usar um plug-in existente , poderá fazer com que o cache do objeto persista por mais tempo que um único carregamento de página. Quando você faz isso, transitório, mude um pouco.
Vamos dar uma olhada na set_transient
função 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;
}
Humm $_wp_using_ext_object_cache
? Se for verdade, o WordPress usa o cache de objetos em vez do banco de dados para armazenar transitórios. Então, como isso é definido? Hora de explorar como o WP configura sua própria API de cache.
Você pode rastrear quase tudo para wp-load.php
ou wp-settings.php
- os quais são cruciais para o processo de inicialização do WordPress. Em nosso cache, existem algumas linhas relevantes wp-settings.php
.
// Start the WordPress object cache, or an external object cache if the drop-in is present.
wp_start_object_cache();
Lembra daquela queda de cima? Vamos dar uma olhada wp_start_object_cache
em 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' ) );
}
}
As linhas relevantes da função (aquelas que pertencem a $_wp_using_ext_object_cache
isso alteram como os transientes são armazenados).
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;
}
se object-cache.php
existir no diretório de conteúdo, ele será incluído e o WP assume que você está usando um cache externo persistente - ele é definido $_wp_using_ext_object_cache
como true.
Se você estiver usando um cache de objeto externo, os transientes o usarão. O que levanta a questão de quando usar opções versus transientes.
Simples. Se você precisar que os dados persistam indefinidamente, use as opções. Eles são "armazenados em cache", mas suas fontes canônicas são o banco de dados e nunca desaparecem, a menos que um usuário solicite explicitamente.
Para dados que devem ser armazenados por um período de tempo definido, mas não precisam persistir além de um tempo de vida útil especificado. Internamente, o WP tentará usar um cache de objeto externo e persistente, caso contrário, os dados entrarão na tabela de opções e serão coletados como lixo através do psuedo-cron do WordPress quando expirarem.
Algumas outras preocupações / perguntas:
- Tudo bem fazer uma tonelada de chamadas
get_option
? Provavelmente. Eles incorrem na chamada para uma sobrecarga de função, mas provavelmente não atingirá o banco de dados. O carregamento do banco de dados geralmente é uma preocupação maior na escalabilidade de aplicativos da Web do que o trabalho que seu idioma preferido gera para gerar uma página.
- Como sei usar transitórios versus a API de cache? Se você espera que os dados persistam por um período definido, use a API transitória. Se não importa se os dados persistem (por exemplo, não demora muito para computar / buscar os dados, mas não deve ocorrer mais de uma vez por carregamento da página), use a API de cache.
- Todas as opções são realmente armazenadas em cache em cada carregamento de página? Não necessariamente. Se você chamar
add_option
com o último argumento opcional, pois no
eles não são carregados automaticamente. Dito isto, depois de buscá-los uma vez, eles entram no cache e as chamadas subseqüentes não atingem o banco de dados.