Le cache de Laravel 5

Voyons aujourd’hui la mise en cache à la sauce Laravel 5. Je rappelle qu’un cache est destiné à accélérer la génération des pages en gardant en mémoire des informations. Le cas le plus classique est celui de requêtes sur une base de données. Si les données ne changent pas fréquemment il est plus efficace de mettre en cache leur résultat plutôt que d’aller chaque fois interroger la base. On peut aussi carrément mettre en cache des pages complètes.

Le principe

Laravel 5 propose un système de cache simple et efficace qui mémorise par défaut les informations dans un fichier. Regardez le fichier app/config/cache.php :

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Cache Store
    |--------------------------------------------------------------------------
    |
    | This option controls the default cache connection that gets used while
    | using this caching library. This connection is used when another is
    | not explicitly specified when executing a given caching function.
    |
    */

    'default' => env('CACHE_DRIVER', 'file'),

    /*
    |--------------------------------------------------------------------------
    | Cache Stores
    |--------------------------------------------------------------------------
    |
    | Here you may define all of the cache "stores" for your application as
    | well as their drivers. You may even define multiple stores for the
    | same cache driver to group types of items stored in your caches.
    |
    */

    'stores' => [

        'apc' => [
            'driver' => 'apc',
        ],

        'array' => [
            'driver' => 'array',
        ],

        'database' => [
            'driver' => 'database',
            'table'  => 'cache',
            'connection' => null,
        ],

        'file' => [
            'driver' => 'file',
            'path'   => storage_path('framework/cache'),
        ],

        'memcached' => [
            'driver'  => 'memcached',
            'servers' => [
                [
                    'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100,
                ],
            ],
        ],

        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Cache Key Prefix
    |--------------------------------------------------------------------------
    |
    | When utilizing a RAM based store such as APC or Memcached, there might
    | be other applications utilizing the same cache. So, we'll specify a
    | value to get prefixed to all our keys so we can avoid collisions.
    |
    */

    'prefix' => 'laravel',

];

Vous trouvez toutes les possibilités de configuration du cache. Vous voyez en premier la façon dont les informations sont stockées :

  • APC
  • array
  • base de données
  • fichier (valeur par défaut)
  • Memcached
  • Redis

Vous trouvez aussi la localisation du fichier (par défaut storage/framework/cache). Le nom de la base et de la table à utiliser dans le cas de stockage en base de données. Le paramétrage de Memcached

Quelle que soit la méthode choisie la classe Cache de Laravel offre les mêmes possibilités de base.

Les commandes de base

Avec une nouvelle installation de Laravel 5 entrez ce code dans le fichier des routes :

Route::get('/', function()
{
    Cache::put('un', '1', 2);
    echo Cache::get('un');
});

Résultat :

1

La méthode put permet de mémoriser une information, le premier paramètre est la clé, le second la valeur et le troisième la durée de conservation de l’information.

La méthode get est l’inverse, elle permet de retrouver une information mémorisée à partir de sa clé.

Regardons maintenant le fichier créé :

img20

Et son contenu :

1443180850s:1:"1";

Il est possible de conserver indéfiniment une information en utilisant la méthode forever :

Cache::forever('un', '1');

Et la méthode forget pour en supprimer une :

Cache::forget('un');

On a aussi la possibilité d’affecter une valeur par défaut en cas d’inexistence de la valeur :

Cache::get('deux', 2);

Vous pouvez aussi récupérer une valeur dans le cache et la mémoriser si elle n’est pas présente :

$value = Cache::remember('un', 1, function()
{
    return 1;
});

Il y a encore d’autres possibilités comme tester l’existence d’une clé, incrémenter ou décrémenter une valeur, récupérer une valeur tout en la supprimant du cache… vous pouvez trouver tout ça dans la documentation.

Un exemple

Voyons maintenant un cas d’application qui justifie l’utilisation d’un cache. Si vous allez sur cette page vous trouvez les sources de la documentation de Laravel 5.1. Il y a en particulier une page avec la table des matières. C’est ce que je vais utiliser pour créer une application pour afficher la documentation de Laravel 5.1 en utilisant un cache pour accélérer le processus.

C’est une chose qui est évidemment déjà réalisée dans l’application du site de Laravel. Mais je vous propose une approche plus simple et du code simplifié.

Vous pouvez tester l’application en ligne en accès normal et avec le cache. Dans cette deuxième version si personne n’a déjà ouvert un lien il faudra y revenir une seconde fois pour voir la différence !

L’installation

Partez d’une nouvelle installation de Laravel 5. Ajoutez deux packages dans composer.json :

"require": {
    "php": ">=5.5.9",
    "laravel/framework": "5.1.*",
    "laravelcollective/html": "5.1.*",
    "erusev/parsedown-extra": "0.7.0"
},

Faites un composer update et c’est bon.

La route

Dans le fichier des routes mettez juste ce code pour appeler un contrôleur :

Route::get('cached/{name?}', 'DocController@showCached');
Route::get('/{name?}', 'DocController@show');

Donc deux routes, une sans cache et l’autre avec le cache pour comparer.

Le contrôleur

Voici le code du contrôleur app/controllers/DocController.php :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Cache;
use ParsedownExtra;

class DocController extends Controller
{

    /**
     * Le parser Markdown.
     *
     * @var ParsedownExtra
     */
    protected $parser = null;

    /**
     * La version de la documentation.
     *
     * @var string
     */
    protected $version = '5.1';

    /**
     * Crée un nouveau DocController.
     *
     * @param  ParsedownExtra $parser
     * @return void
     */
    public function __construct(ParsedownExtra $parser)
    {
        $this->parser = $parser;
    }

    /**
     * Récupère, nettoie et parse Markdown d'une url
     */
    private function getCleanParseHtml($url, $cached = '/')
    {
        // Récupération du contenu
        $doc = file_get_contents($url);

        // Nettoyage des liens
        $doc = str_replace('/docs/{{version}}', url($cached), $doc);    

        // Cas de l'API
        $doc = str_replace('/api/{{version}}', 'http://laravel.com/api/' . $this->version, $doc); 

        // Parser
        $doc = $this->parser->text($doc);  

        // Ajout prettyprint
        $doc = str_replace('<pre>', '<pre class="prettyprint">', $doc);   
        
        return $doc;     
    }

    /**
     * Récupération de la navigation
     */
    private function getNav($cached)
    {
        $nav = $this->getCleanParseHtml('https://raw.githubusercontent.com/laravel/docs/' . $this->version .'/documentation.md', $cached);
        
        return $nav;     
    }   

    /**
     * Récupération du contenu
     */
    private function getContent($name, $cached)
    {
        $content = $this->getCleanParseHtml('https://github.com/laravel/docs/raw/' . $this->version .'/' . $name . '.md', $cached);

        return $content;     
    }  
 
    /**
     * Affichage de la page.
     */
    public function show($name = 'installation')
    {
        // Navigation
        $nav = $this->getNav('/');
       
        // Contenu
        $content = $this->getContent($name, '/');

        // Affichage de la vue
        return view('main', array_merge(compact('nav', 'content'), ['version' => $this->version]));
    }

    /**
     * Affichage de la page avec le cache
     */
    public function showCached($name = 'installation')
    {
        // Navigation
        $nav = Cache::remember('nav', 60, function() {
            return $this->getNav('cached');
        });
 
        // Contenu
        $content = Cache::remember($name, 60, function() use ($name) {
            return $this->getContent($name, 'cached');  
        });

        // Affichage de la vue
        return view('main', array_merge(compact('nav', 'content'), ['version' => $this->version]));
    }
}

En gros le code permet d’aller récupérer le code de la documentation, de sélectionner juste ce qui est utile, de modifier les liens et d’ajouter la classe pour la présentation du code. La version de la documentation figure dans la propriété version, donc il suffit de la changer pour accéder à la documentation correspondante, si elle existe…

La vue

On a juste besoin d’une vue resources/views/main.blade.php :

<!DOCTYPE Html>
<head>
  <meta charset="utf-8">
  <title>Laravel documentation</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  {!! Html::style('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css') !!}
  <style type="text/css">
    body {
      background-color: #ddd;
    }
    ul {
      list-style-type: none;
    }
    hr {
      border-color: white;
    }
    ul > li {
      font-size: 18px;
      font-weight: 400;
      padding: 0 0 10px;
    }
    ul > li > ul > li {
      font-size: 14px;
      padding: 0;
    }
    .col-sm-3 {
      border-right-style: solid;
      border-right-width: 1px;
      border-right-color: white;
    }
  </style>
</head>
 
<body>
  <div class="container">
    <h1>Documentation de Laravel {{ $version }}</h1>
    <hr>
    <div class="row">
      <nav class="col-sm-3">
        {!! $nav !!}
      </nav>
      <section class="col-sm-9">
        {!! $content !!}
      </section>
    </div>
  </div>
  {!! Html::script('https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js') !!}
</body>

On charge Bootstrap pour la mise en forme, on prévoit deux variables pour la navigation et le contenu et on charge Prettify pour la coloration syntaxique du code. La version de la documentation est dans la variable $version.

Et voici l’apparence du résultat :

img21

Les liens doivent fonctionner et la présentation est sobre et agréable (bon enfin c’est à mon goût vous pouvez changer tout ce que vous voulez !).

La version sans cache est accédée avec l’url de base ‘/’ et la version avec cache avec l’url ‘/cached/’.

J’espère que cet article vous aura donné envie d’utiliser le cache.

Laisser un commentaire