Blog

Sígueme en

WordPress ACF: cacheando las opciones

   WordPress


Advanced Custom Fields (ACF) es una maravilla de plugin que nos hace la vida más fácil a la hora de agregar nuevos campos y gestionar el contenido de posts, custom posts, etc. desde el panel de WordPress. Pero tanta simplicidad tiene un pequeño impacto en el rendimiento y sobre todo en el número de queries.

Resulta que cuando quieres obtener un valor de uno de los campos de ACF, y lo haces mediante la función get_field(), en realidad ACF realiza 2 queries para cada campo. Una solución es utilizar get_post_meta() en lugar de get_field(), ya que al fin y al cabo, ACF guarda los datos en la tabla (wp)_postmeta(). Pero ciertos campos, tienen una configuración especial como por ejemplo los campos de tipo fecha, donde le decimos a ACF que muestre la fecha de una manera y la recoja de otra por ejemplo. En esos casos, recoger el valor con get_post_meta() no nos va a devolver el resultado formateado y de la manera que queremos, así que por defecto, es conveniente utilizar siempre la función get_field() que nos ofrece ACF.

Bien, entonces, para poder utilizar siempre esa función y a la vez reducir el número de queries necesarias, podemos utilizar las funciones de caché que incorpora el propio WordPress, sin necesidad de plugins. Para este caso, el sistema que utilizaremos será el de caché persistente, que lo que hace es almacenar los datos en la bbdd, para que la siguiente vez que se pida se necesite una única query para recoger todos los campos, en vez de 2 queries por cada campo.

Para que os hagáis una idea, si tenemos 5 campos configurados en la página de opciones de ACF, necesitaría 10 queries para obtener todos los datos. Lo que vamos a conseguir es que sólo se necesite 1 query independientemente del número de campos que recojamos. Evidentemente la primera vez, cuando todavía no haya caché almacenado, necesitará 10 queries, pero las siguientes veces y para todos los usuarios que visiten la web, sólo se utilizará 1 query.

Para empezar, vamos a definir una variable global donde almacenaremos todas las opciones. Primero miraremos si tenemos el transient disponible para recoger las opciones, y si no lo tenemos, entonces será cuando utilizaremos get_field() para recoger cada una de las opciones, que asignaremos a la variable global y que guardaremos en caché mediante la función set_transient().

add_action('init', 'ow_acf_global_options');
function ow_acf_global_options() {
    global $ow_acf_options;

    $ow_acf_options = get_transient('ow_acf_options');

    if (empty($ow_acf_options)) :

        $options = array (
            'texto_footer',
            'facebook',
            'twitter',
            'google_plus',
            'instagram',
            'youtube'
        );

        foreach ($options as $opt) :
            $ow_acf_options[$opt] = get_field($opt, 'options');
        endforeach;

        set_transient('ow_acf_options', $ow_acf_options);

    endif;
}

Utilizando este método, es cierto que estamos recogiendo todas las opciones en todas las páginas, tenedlo en cuenta, porque a lo mejor no queréis este comportamiento, aunque de todas formas, se recogen utilizando una única querie independientemente del número de opciones. Personalmente, lo suelo utilizar para opciones generales que deben ser cargadas en todas las secciones del sitio, por eso en el ejemplo he utilizado las típicas opciones de enlaces a redes sociales o un texto en el footer.

Por último, cuando queremos que el transient que tenemos guardado se actualice de nuevo porque su contenido ha cambiado, cosa que en este caso ocurre únicamente si se edita la página de opciones, podemos utilizar un hook que nos proporciona ACF para eliminar el transient de la siguiente manera:

add_action('acf/save_post', 'ow_acf_clear_cache', 20);
function ow_acf_clear_cache() {
    $screen = get_current_screen();
    if (strstr($screen->id, 'acf-options')) {
        delete_transient('ow_acf_options');
    }
}

Más información sobre las funciones para gestionar transients de WordPress aquí:

WordPress Transients_API