La mise en cache

class Cake\Cache\Cache

La mise en cache est fréquemment utilisée pour réduire le temps pris pour créer ou lire depuis une autre ressource. La mise en cache est souvent utilisée pour rendre la lecture de ressources consommatrices en temps, en ressources moins consommatrice. Vous pouvez aisément stocker en cache les résultats de requêtes consommatrices en ressources ou les accès à distance à des services web qui ne changent pas fréquemment. Une fois mis en cache, re-lire les ressources stockées depuis le cache est moins consommateur en ressource qu’un accès à une ressource distante.

La mise en cache dans CakePHP se fait principalement par la classe Cache. Cette classe fournit un ensemble de méthodes statiques qui fournissent une API uniforme pour le traitement des différentes implémentations de mise en cache. CakePHP dispose de plusieurs moteurs de cache intégrés, et fournit un système facile pour implémenter votre propre système de mise en cache. Les moteurs de cache intégrés sont:

  • FileCache File cache est un cache simple qui utilise des fichiers locaux. C’est le moteur de cache le plus lent, et il ne fournit que peu de fonctionnalités pour les opérations atomiques. Cependant, le stockage sur disque est souvent peu consommateur en ressource, le stockage de grands objets ou des éléments qui sont rarement écrits fonctionne bien dans les fichiers.

  • ApcCache Le cache APC utilise l’extension PHP APCu. Cette extension utilise la mémoire partagée du serveur Web pour stocker les objets. Cela le rend très rapide, et capable de fournir les fonctionnalités atomiques en lecture/écriture.

  • Wincache Utilise l’extension Wincache. Wincache offre des fonctionnalités et des performances semblables à APC, mais optimisées pour Windows et IIS.

  • XcacheEngine Xcache. est une extension PHP qui fournit des fonctionnalités similaires à APC.

  • MemcachedEngine Utilise l’extension Memcached.

  • RedisEngine Utilise l’extension phpredis. Redis fournit un système de cache cohérent et rapide similaire à Memcached et il permet aussi les opérations atomiques.

Quelque soit le moteur de cache que vous choisirez d’utiliser, votre application interagit avec Cake\Cache\Cache de manière cohérente. Cela signifie que vous pouvez aisément permuter les moteurs de cache en fonction de l’évolution de votre application.

Configuration de la classe Cache

static Cake\Cache\Cache::config($key, $config = null)

La configuration de la classe Cache peut être effectuée n’importe où, mais généralement vous voudrez configurer le cache pendant la phase de bootstrap. le fichier config/app.php est le lieu approprié pour cette configuration. Vous pouvez configurer autant de configurations de cache dont vous avez besoin, et vous pouvez utiliser tous les mélanges de moteurs de cache. CakePHP utilise deux configurations de cache en interne. _cake_core_ est utilisé pour stocker des correspondances de fichiers, et les résultats parsés des fichiers de traduction . _cake_model_ est utilisé pour stocker les schémas des models de vos applications. Si vous utilisez APC ou Memcached vous devrez vous assurer de définir des clés uniques pour les caches du noyau. Ceci vous évitera qu’une application vienne réécrire les données cache d’une autre application.

L’utilisation de plusieurs configurations vous permet également de changer le stockage comme vous l’entendez. Par exemple vous pouvez mettre ceci dans votre config/app.php:

// ...
'Cache' => [
    'short' => [
        'className' => 'File',
        'duration' => '+1 hours',
        'path' => CACHE,
        'prefix' => 'cake_short_'
    ],
    // Utilisation d'un espace de nom complet.
    'long' => [
        'className' => 'Cake\Cache\Engine\FileEngine',
        'duration' => '+1 week',
        'probability' => 100,
        'path' => CACHE . 'long' . DS,
    ]
]
// ...

Les options de configuration peuvent également être fournies en tant que chaine DSN. C’est utile lorsque vous travaillez avec des variables d’environnement ou des fournisseurs PaaS:

Cache::config('short', [
    'url' => 'memcached://user:password@cache-host/?timeout=3600&prefix=myapp_',
]);

Lorsque vous utilisez une chaine DSN, vous pouvez définir des paramètres/options supplémentaires en tant qu’arguments de query string.

Vous pouvez également configurer les moteurs de cache pendant l’exécution:

// Utilisation d'un nom court
Cache::config('short', [
    'className' => 'File',
    'duration' => '+1 hours',
    'path' => CACHE,
    'prefix' => 'cake_short_'
]);

// Utilisation d'un espace de nom complet.
Cache::config('long', [
    'className' => 'Cake\Cache\Engine\FileEngine',
    'duration' => '+1 week',
    'probability' => 100,
    'path' => CACHE . 'long' . DS,
]);

// utilisation d'un objet.
$object = new FileEngine($config);
Cache::config('other', $object);

Note

Vous devez spécifier le moteur à utiliser. Il ne met pas File par défaut.

En insérant le code ci-dessus dans votre config/app.php vous aurez deux configurations de cache supplémentaires. Le nom de ces configurations “short” ou “long” est utilisé comme paramètre $config pour Cake\Cache\Cache::write() et Cake\Cache\Cache::read(). Lors de la configuration des moteurs de cache, vous pouvez vous référer au nom de la classe en utilisant les syntaxes suivantes:

  • Un nom raccourci sans “Engine” ou namespace (espace de nom). Il déduira que que vous voulez utiliser Cake\Cache\Engine ou App\Cache\Engine.

  • Utiliser la syntaxe de plugin qui permet de charger des moteurs depuis un plugin spécifique.

  • Utiliser un nom de classe complet incluant le namespace. Cela vous permet d’utiliser des classes situées en dehors des emplacements classiques.

  • Utiliser un objet qui étend la classe CacheEngine

Note

Lorsque vous utilisez le FileEngine vous pourriez avoir besoin d’utiliser l’option mask pour assurer que les fichiers de cache sont créés avec les autorisations nécessaires.

Configurer un Fallback de Cache

Dans le cas où un moteur de cache n’est pas disponible, comme par exemple le FileEngine essayant d’écrire dans un dossier sans les droits d’écriture ou le RedisEngine n’arrivant pas à se connecter à Redis, le moteur se repliera sur le moteur “noop” NullEngine et déclenchera une erreur qui sera loggée. Cela permet d’éviter que l’application lance une exception qui ne sera pas interceptée à cause d’une erreur de cache.

Vous pouvez configurer vos configurations de Cache pour se replier sur une configuration spécifique en utilisant la clé de configuration fallback:

Cache::config('redis', [
    'className' => 'Redis',
    'duration' => '+1 hours',
    'prefix' => 'cake_redis_',
    'host' => '127.0.0.1',
    'port' => 6379,
    'fallback' => 'default',
]);

Si le serveur Redis tombait en erreur de manière inattendue, l’écriture dans le cache avec la configuration redis se repliera sur la configuration default. Si l’écriture dans la configuration default échouait elle aussi, le moteur se replierait à nouveau sur un autre “fallback”, ici le NullEngine, et empêcherait l’application de lancer une exception.

Suppression de Configuration de Cache

static Cake\Cache\Cache::drop($key)

Une fois la configuration créée, vous ne pouvez pas la changer. Au lieu de cela, vous devriez supprimer la configuration et la re-créer à l’aide de Cake\Cache\Cache::drop() et Cake\Cache\Cache::config(). Supprimer un moteur de cache va supprimer la configuration et détruire l’adaptateur s’il a été construit.

Ecrire dans un Cache

static Cake\Cache\Cache::write($key, $value, $config = 'default')

Cache::write() stocke $value dans le Cache. Vous pouvez lire ou supprimer cette valeur plus tard en vous y reférant via $key. Vous pouvez spécifier une configuration optionnelle pour y stocker le cache. Si aucune $config n’est spécifiée, la configuration par défaut sera utilisée. Cache::write() peut stocker tout type d’objet et est idéale pour stocker les résultats des “finds” de vos models:

if (($posts = Cache::read('posts')) === false) {
    $posts = $unService->getAllPosts();
    Cache::write('posts', $posts);
}

Utiliser Cache::write() et Cache::read() réduira le nombre d’allers-retours effectués vers la base de données pour récupérer les messages.

Note

Si vous prévoyez de mettre en cache le résultat de requêtes faites avec l’ORM de CakePHP, il est préférable d’utiliser les fonctionnalités de cache intégrées dans l’objet Query, telles que décrites dans la section mettre les résultats de requête en cache

Ecrire Plusieurs Clés d’un Coup

static Cake\Cache\Cache::writeMany($data, $config = 'default')

Vous pouvez avoir besoin d’écrire plusieurs clés du cache à la fois. Bien que vous pouvez utiliser plusieurs appels à write(), writeMany() permet à CakePHP l’utilisation d’une API de stockage plus efficace quand cela est possible. Par exemple utiliser writeMany() permet de gagner de nombreuses connections réseau lors de l’utilisation de Memcached:

$result = Cache::writeMany([
    'article-' . $slug => $article,
    'article-' . $slug . '-comments' => $comments
]);

// $result va contenir
['article-first-post' => true, 'article-first-post-comments' => true]

Lire un Cache Distribué

static Cake\Cache\Cache::remember($key, $callable, $config = 'default')

Cache permet la lecture d’un cache distribué. Si la clé de cache demandée existe, elle sera retournée. Si la clé n’existe pas, le callable sera invoqué et les résultats stockés dans le cache pour la clé fournie.

Par exemple, vous souhaitez souvent mettre en cache les résultats du appel à un service distant. Vous pouvez utiliser remember() pour faciliter cela:

class IssueService
{

    function allIssues($repo)
    {
        return Cache::remember($repo . '-issues', function () use ($repo) {
            return $this->fetchAll($repo);
        });
    }

}

Lire depuis un Cache

static Cake\Cache\Cache::read($key, $config = 'default')

Cache::read() est utilisée pour lire la valeur mise en cache stockée dans $key dans la $config. Si $config est null la configuration par défaut sera utilisée. Cache::read() renverra la valeur mise en cache si le cache est valide ou false si le cache a expiré ou n’existe pas. Le contenu du cache peut être mal évalué, donc assurez vous d’utiliser les opérateurs de comparaison stricts: ===` ou !==.

Par exemple:

$cloud = Cache::read('cloud');

if ($cloud !== false) {
    return $cloud;
}

// Genère des données cloud
// ...

// Stocke les données en cache
Cache::write('cloud', $cloud);
return $cloud;

Lire Plusieurs Clés d’un Coup

static Cake\Cache\Cache::readMany($keys, $config = 'default')

Après avoir écrit plusieurs clés d’un coup, vous voudrez probablement les lire également. Bien que vous pouvez utiliser plusieurs appels à read(), readMany()``permet à CakePHP l'utilisation d'une API de stockage plus efficace quand cela est possible. Par exemple utiliser ``readMany() permet de gagner de nombreuses connections réseau lors de l’utilisation de Memcached:

$result = Cache::readMany([
    'article-' . $slug,
    'article-' . $slug . '-comments'
]);
// $result contiendra
['article-first-post' => '...', 'article-first-post-comments' => '...']

Suppression d’un Cache

static Cake\Cache\Cache::delete($key, $config = 'default')

Cache::delete() vous permettra de supprimer complètement un objet mis en cache du stockage:

// Supprime la clé
Cache::delete('my_key');

Supprimer Plusieurs Clés d’un Coup

static Cake\Cache\Cache::deleteMany($keys, $config = 'default')

Après avoir écrit plusieurs clés d’un coup, vous voudrez probablement les supprimer également. Bien que vous pouvez utiliser plusieurs appels à delete(), deleteMany() permet à CakePHP l’utilisation d’une API de stockage plus efficace quand cela est possible. Par exemple utiliser deleteMany() permet de gagner de nombreuses connections réseau lors de l’utilisation de Memcached:

$result = Cache::deleteMany([
    'article-' . $slug,
    'article-' . $slug . '-comments'
]);
// $result contiendra
['article-first-post' => true, 'article-first-post-comments' => true]

Effacer les Données du Cache

static Cake\Cache\Cache::clear($check, $config = 'default')

Détruit toute les valeurs pour une configuration de cache. Pour les moteurs tels que APC, Memcached et Wincache, le préfixe de la configuration du cache est utilisé pour supprimer les données de cache. Assurez-vous que les différentes configurations de cache ont des préfixes différents:

// Détruira uniquement les clés expirées.
Cache::clear(true);

// Détruira toutes les clés.
Cache::clear(false);
static Cake\Cache\Cache::gc($config)

Garbage collects entries in the cache configuration. C’est principalement utilisé par FileEngine. Elle ne devra être implémentée par tout moteur de Cache qui a besoin d’une suppresion manuelle des données mises en cache.

Note

Comme APC et Wincache utilisent des caches isolés pour le serveur web et le CLI, ils doivent être supprimés séparément (CLI ne peut pas nettoyer le serveur web et vice et versa).

Utiliser le Cache pour Stocker les Compteurs

static Cake\Cache\Cache::increment($key, $offset = 1, $config = 'default')
static Cake\Cache\Cache::decrement($key, $offset = 1, $config = 'default')

Les compteurs de votre application sont de bons candidats pour le stockage dans un cache. Par exemple, un simple compte à rebours pour des places restantes dans un concours peut être stocké dans le cache. La classe Cache expose des opérations atomiques pour incrémenter/décrémenter les valeurs du compteur. Les opérations atomiques sont importantes pour ces valeurs, car elle réduisent le risque de contention, et la capacité pour deux utilisateurs d’abaisser simultanément la valeur, ce qui entraînerait une valeur incorrecte.

Après avoir défini une valeur entière, vous pouvez la manipuler à l’aide des fonctions increment() et decrement():

Cache::write('initial_count', 10);

// Plus tard
Cache::decrement('initial_count');

// Ou
Cache::increment('initial_count');

Note

L’incrémentation et la décrementation ne fonctionne pas avec FileEngine. A la place, vous devez utiliser APC, Wincache, Redis ou Memcached.

Utiliser le Cache pour Stocker les Résultats de Requêtes Courantes

Vous pouvez considérablement améliorer les performances de votre application en mettant dans le cache les résultats qui changent rarement, ou qui sont soumis à de nombreuses lectures. Un exemple parfait serait les résultats de Cake\ORM\Table::find(). l’objet Query vous permet de mettre les résultats en cache en utilisant la méthode cache. Voir la section mettre les résultats de requête en cache pour plus d’information.

Utilisation des Groupes

Parfois vous voudrez marquer plusieurs entrées de cache comme appartenant à un même groupe ou un namespace. C’est une exigence courante pour invalider de sgrosses quantités de clés alors que quelques changements d’informations sont partagés pour toutes les entrées dans un même groupe. Cela est possible en déclarant les groupes dans la configuration de cache:

Cache::config('site_home', [
    'className' => 'Redis',
    'duration' => '+999 days',
    'groups' => ['comment', 'article']
]);
Cake\Cache\Cache::clearGroup($group, $config = 'default')

Disons que vous voulez stocker le HTML généré pour votre page d’accueil dans le cache, mais vous voulez aussi invalider automatiquement ce cache à chaque fois qu’un commentaire ou un post est ajouté à votre base de données. En ajoutant les groupes comment et article, nous avons effectivement taggé les clés stockées dans la configuration du cache avec les noms des deux groupes.

Par exemple, dès qu’un post est ajouté, nous pouvons dire au moteur de Cache de retirer toutes les entrées associées au groupe article:

// src/Model/Table/ArticlesTable.php
public function afterSave($event, $entity, $options = [])
{
    if ($entity->isNew()) {
        Cache::clearGroup('article', 'site_home');
    }
}
static Cake\Cache\Cache::groupConfigs($group = null)

groupConfigs() peut être utilisée pour récupérer la correspondance entre des groupes et des configurations, par exemple ayant le même groupe:

// src/Model/Table/ArticlesTable.php

/**
 * Une variante de l'exemple précédent qui efface toutes les configurations
 * ayant le même groupe
 */
public function afterSave($event, $entity, $options = [])
{
    if ($entity->isNew()) {
        $configs = Cache::groupConfigs('article');
        foreach ($configs['article'] as $config) {
            Cache::clearGroup('article', $config);
        }
    }
}

Les groupes sont partagés à travers toutes les configs de cache en utilisant le même moteur et le même préfixe. Si vous utilisez les groupes et voulez tirer profit de la suppression de groupe, choisissez un préfixe commun pour toutes vos configs.

Activer ou Désactiver Globalement le Cache

static Cake\Cache\Cache::disable

Vous pourriez avoir besoin de désactiver toutes les lectures/écritures du Cache en essayant de comprendre des problèmes liés à l’expiration du cache. Vous pouvez le faire en utilisant enable() et disable():

// Désactive toutes les lectures/écritures
Cache::disable();

Une fois désactivé, toutes lecture/écriture renverra null.

static Cake\Cache\Cache::enable

Une fois désactivé, utilisez enable() pour réactiver le cache:

// Active de nouveau toutes les lectures/écritures
Cache::enable();
static Cake\Cache\Cache::enabled

Si vous voulez vérifier l’état du Cache, utilisez enabled().

Création d’un moteur de stockage pour le Cache

Vous pouvez fournir vos propre adaptateurs Cache dans App\Cache\Engine ou dans un plugin en utilisant $plugin\Cache\Engine. Les moteurs de cache src/plugin peuvent aussi remplacer les moteurs du cœur. Les adaptateurs de cache doivent être dans un répertoire cache. Si vous avez un moteur de cache nommé MyCustomCacheEngine il devra être placé soit dans src/Cache/Engine/MyCustomCacheEngine.php comme une app/libs ou dans plugin/Cache/Engine/MyCustomCacheEngine.php faisant parti d’un plugin. Les configurations de cache venant d’un plugin doivent utiliser la notation par points de plugin:

Cache::config('custom', [
    'engine' => 'CachePack.MyCustomCache',
    // ...
]);

Les moteurs de cache personnalisés doivent étendre Cake\Cache\CacheEngine qui définit un certain nombre de méthodes d’abstraction ainsi que quelques méthodes d’initialisation.

L’API requise pour CacheEngine est

class Cake\Cache\CacheEngine

La classe de base pour tous les moteurs de cache utilisée avec le Cache.

Cake\Cache\CacheEngine::write($key, $value, $config = 'default')
Retourne:

un booléen en cas de succès.

Écrit la valeur d’une clé dans le cache, la chaîne optionnelle $config spécifie le nom de la configuration à écrire.

Cake\Cache\CacheEngine::read($key)
Retourne:

La valeur mise en cache ou false en cas d’échec.

Lit une clé depuis le cache. Retourne false pour indiquer que l’entrée a expiré ou n’existe pas.

Cake\Cache\CacheEngine::delete($key)
Retourne:

Un booléen true en cas de succès.

Efface une clé depuis le cache. Retourne false pour indiquer que l’entrée n’existe pas ou ne peut être effacée.

Cake\Cache\CacheEngine::clear($check)
Retourne:

Un booléen true en cas de succès.

Efface toutes les clés depuis le cache. Si $check est à true, vous devez valider que chacune des valeurs a réellement expirée.

Cake\Cache\CacheEngine::clearGroup($group)
Renvoie:

Un booléen true en cas de succès.

Supprime toutes les clés à partir du cache appartenant au même groupe.

Cake\Cache\CacheEngine::decrement($key, $offset = 1)
Retourne:

Un booléen true en cas de succès.

Décrémente un nombre dans la clé et retourne la valeur décrémentée

Cake\Cache\CacheEngine::increment($key, $offset = 1)
Retourne:

Un booléen true en cas de succès.

Incrémente un nombre dans la clé et retourne la valeur incrémentée

static Cake\Cache\CacheEngine::gc

Non requise, mais utilisée pour faire du nettoyage quand les ressources expirent. Le moteur FileEngine utilise cela pour effacer les fichiers qui contiennent des contenus expirés.