Un breve preambolo. In questo articolo non parlerò di cache persistente, attuabile in worpress con l’uso di plugin o sfruttando i transient, ma della possibilità di mettere in cache il risultato di una query che si ripeta all’interno del ciclo di esecuzione di una singola pagina; l’oggetto wp_object_cache viene infatti distrutto alla fine dell’esecuzione del codice.

Facciamo un esempio pratico

Un esempio pratico può essere rappresentato dall’uso della funzione:

wp_get_object_terms( $id, $taxonomy, $args );

Nel nostro esempio wp_get_object_terms() viene usato più volte nella pagina per ottenerne le categorie di appartenenza, generando una query al database per ogni richiamo… verifichiamolo!

$array = array();
for ( $i = 0; $i < 10; $i++ ) {
	$array[] = wp_get_object_terms( 399, 'category', array( 'fields' => 'ids' ) );
}

Risultato:

10 richieste, 10 query in 0.002112 secondi, memoria consumata 5176 byte.

Ci rendiamo subito conto di quanto sia assurdo eseguire 10 query al database quando, dopo la prima volta, il risultato potrebbe essere memorizzato per una rapida consultazione.

Entra in scena wp_object_cache

Quando mi sono trovato questo problema davanti ho pensato di dover scrivere una classe, istanziata come oggetto globale, per gestire la cache. Dopo una rapida ricerca sul codex ho però scoperto che il codice di WordPress contiene già tutto quanto ci possa servire a gestire la cache.

Sto ovviamente parlando di wp_object_cache, classe istanziata come oggetto globale che permette, grazie alle funzioni di supporto, di ricavare dati di cui si sia già effettuata una query.

Seppur ci siano numerose funzioni di supporto, per quanto previsto in questo esempio, necessitiamo conoscere solo le due che seguono.

wp_cache_set( $key, $data, $group, $expire )

wp_cache_set() permette di settare la nostra cache. Il parametro $key corrisponde all’identificatore unico della posizione in cache, $data è il risultato della query da memorizzare, $group è il gruppo di riferimento e permette di adottare la medesima chiave in ambiti diversi. $expire non è rilevante per questo esempio.

wp_cache_get( $key, $group = '', $force = false, $found = null )

wp_cache_get() restituisce l’oggetto in cache o false se non trova risultati, per evitare ambiguità prevede inoltre un parametro $found cui viene passato, per riferimento, l’esito dell’operazione. $force non è rilevante per questo esempio.

Implementiamo la cache nel nostro esempio

Grazie a queste nuove informazioni ora siamo in grado di scrivere una funzione che permetta di salvare il risultato della query in cache usandone i parametri come chiave unica in modo da potervi accedere alla successiva richiesta.

Nell’esempio che segue utilizziamo appunto tale tecnica con la peculiarità di combinare md5() e , cui vengono passati i parametri di wp_get_object_terms(), per ottenere una chiave unica:

/**
 * Versione cache di wp_get_object_terms
 */
function cached_wp_get_object_terms( $id, $taxonomy, $args = array() ) {
	
	// Creo una chiave unica
	$key = md5( serialize( array( $id, $taxonomy, $args ) ) );
	
	// Cerco i risultati nella cache
	$my_terms = wp_cache_get( $key, 'mc_wp_get_object_terms', false, $found );
	
	// Se il risultato non si trova gia nella cache
	if ( $found === false ){
		
		// Eseguo la query
		$my_terms = wp_get_object_terms( $id, $taxonomy, $args );
		
		// Salvo la query nella cache
		wp_cache_set( $key, $my_terms, 'mc_wp_get_object_terms' );
	}
	
	// Ritorno il risultato
	return $my_terms;
}

$array = array();
for ( $i = 0; $i < 10; $i++ ) {
	$array[] = cached_wp_get_object_terms( 399, 'category', array( 'fields' => 'ids' ) );
}

Risultato:

10 richieste, 1 query in 0.000195 secondi, memoria consumata -3936 byte.

I risultati parlano da soli. Meno query con conseguente risparmio di risorse (php e database) nonché minor tempo di esecuzione. Il dato strano è che il consumo di memoria risulta negativo, in realtà tale consumo esiste ma è vanificato da un qualche altro processo che ne libera in quantità maggiore.

Quando usare la cache integrata in WordPress

Considerato che WordPress prevede già il caching non persistente di molte delle query effettuate e che mettere in memoria i risultati della query comporta comunque un consumo di risorse wp_object_cache andrebbe utilizzata solo quando necessario.

Il codex di WordPress specifica infatti che ne è consigliato l’uso per query particolarmente complesse ed esose in risorse. Io aggiungerei per tutte quelle query che vengono usate molto spesso all’interno della medesima pagina.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *