O cache é essencial para alcançar um alto desempenho e escalabilidade. A implementação da estratégia de cache adequada desde a fase de desenvolvimento é fundamental para evitar APIs atrasadas e tempos de carregamento de páginas lentos. Laravel é um dos frameworks PHP mais populares, portanto implementar a estratégia ideal de cache do Laravel é indispensável para uma melhor experiência do usuário e maior impacto nos negócios.

Neste artigo, vamos explorar estratégias para implementar e manipular o cache do Laravel. Você aprenderá sobre como o cache do Laravel funciona, várias consultas de cache do Laravel e como você pode lidar com o cache em aplicativos Laravel.

Você se beneficiará mais com este artigo se já tiver algum conhecimento básico sobre o seguinte:

Vamos nessa!

Confira nosso guia em vídeo sobre o Cache Laravel

Por que o cache é importante?

Com o recente boom nos negócios da internet, diferentes empresas têm estatísticas mostrando como o tempo de carregamento do site e o baixo desempenho podem impactar fortemente o SEO, o envolvimento do usuário e as taxas de conversação sem cache. E isso começa com uma excelente estratégia de cache em vigor.

Um estudo on-line descobriu que “1 segundo de tempo de atraso de carregamento custaria à Amazon 1,6 bilhões de dólares em vendas por ano”.

Outro estudo do Google relatou: “Nossa pesquisa mostra que se os resultados da pesquisa forem desacelerados por uma fração de segundo, as pessoas pesquisam menos (a sério: Um atraso de 400ms leva a uma queda de 0,44 por cento no volume de pesquisas). E essa impaciência não se limita apenas à pesquisa: Quatro em cada cinco usuários da Internet irão embora se um vídeo parar durante o carregamento.”

Uma leve lentidão no tempo de carregamento da sua página web pode ter um impacto maciço na experiência de seus usuários e na perda de fundos em geral.

O que é cache do Laravel?

Laravel fornece uma implementação robusta e fácil de usar o cache e diferentes back-ends de cache. Com o cache Laravel, você pode alternar de forma eficiente e eficaz entre muitos mecanismos de cache sem escrever nenhum código.

Você pode encontrar a configuração do cache Laravel dentro da pasta config/cache.php, embora você provavelmente só precisará do arquivo .env para alternar entre diferentes back-ends de cache.

O cache Laravel também fornece muitos métodos práticos que podemos usar para implementar diferentes estratégias de cache.

Drivers de cache do Laravel e comparações

O cache Laravel fornece grandes back-end de cache e drivers. Dependendo do seu caso de uso, você pode alternar entre eles para melhorar o desempenho do seu aplicativo e o tempo de carregamento.

Dito isto, o cache Laravel também oferece uma forma perfeita de criar um back-end personalizado e usá-lo com o cache Laravel, mas apenas se a lista abaixo não se adequar ao seu caso de uso.

A seguir vamos falar sobre a lista de todos os back-ends fornecidos pelo cache do Laravel.

1. file

O driver file é o back-end padrão usado pelo cache do Laravel quando nenhum driver é especificado no arquivo .env.

O back-end do file é projetado para armazenar os dados em cache em um arquivo criptografado encontrado sob storage/framework/. Laravel cria um arquivo criptografado com os dados e a chave de cache quando novos dados são armazenados em cache. O mesmo acontece quando o usuário está tentando recuperar o conteúdo. O cache Laravel pesquisa na pasta a chave especificada e, se encontrada, retorna o conteúdo.

Embora o back-end do file funcione sem falhas e poupe tempo na instalação e configuração de drivers externos, ele também pode ser perfeito para o desenvolvimento. É mais rápido do que acessar os dados diretamente do servidor de banco de dados.

Para usar o driver do file, adicione o seguinte código ao seu arquivo .env:

CACHE_DRIVER=file

2. Array

O driver array é um back-end de cache perfeito para executar testes automáticos e é configurado facilmente com Github Actions, Jenkins, etc.

O back-end do array armazena os dados em cache em um array em PHP e não requer que você instale ou configure nenhum driver. Ele funciona perfeitamente para testes automatizados, e é um pouco mais rápido que o back-end do cache de arquivos.

Para usar o driver array , adicione o seguinte código ao seu arquivo .env:

CACHE_DRIVER=array

3. Database

Ao usar o driver database, os dados são armazenados na memória para o processo PHP atual. Portanto, você precisa criar uma tabela de banco de dados para armazenar os dados em cache. Além disso, o cache de banco de dados melhora a escalabilidade, distribuindo a carga de trabalho da consulta a partir do back-end para múltiplos frontends.

Você pode executar este comando Artisan — php artisan cache:table — para auto-gerar o esquema de base de dados necessário para o driver database.

O driver database é usado principalmente em situações em que você pode instalar qualquer software na sua plataforma de hospedagem.

Por exemplo, digamos que você está usando um plano de hospedagem gratuito com opções limitadas. Para isso, sugerimos ficar com o driver file porque o driver database é, na maioria dos casos, o ponto mais fraco do seu aplicativo, e tentar empurrar mais dados para esse gargalo não é uma boa idéia.

Para usar o driver database, adicione o seguinte código ao seu arquivo .env:

CACHE_DRIVER=database

4. Redis

O driver redis usa a tecnologia de cache baseada na memória chamada Redis. Embora seja rápido em comparação com os outros drivers de cache discutidos acima, ele requer a instalação e configuração de tecnologia externa.

Para usar o driver redis, adicione o seguinte código ao seu arquivo .env:

CACHE_DRIVER=redis

5. Memcached

Memcached é conhecida por ser a mais popular loja de cache baseada em memória. Se você não se importa com um pouco de manutenção extra do servidor (ter que instalar e manter serviços adicionais), os drivers de cache baseados em memória Memcached são ótimas opções.

O uso do driver memcached requer que o pacote PECL Memcached seja instalado.

Para usar o driver memcached, adicione o seguinte código ao seu arquivo .env.

CACHE_DRIVER=memcached 

O melhor driver de cache para usar e o desempenho do driver de cache dependem do caso de uso do seu projeto e da quantidade de dados a serem recuperados.

Uso e métodos do cache do Laravel

O cache do Laravel fornece muitos métodos valiosos usados para implementar muitas estratégias de cache.

Abaixo listaremos e explicaremos os diferentes métodos (categorizados de acordo com o caso de uso):

  1. put()
  2. get()
  3. many()
  4. putMany()
  5. increment()
  6. decrement()
  7. forever()
  8. forget()
  9. flush()
  10. remember()
  11. rememberForever()

Armazenamento de Cache

O armazenamento de novos dados no cache é muito simples usando os diferentes métodos, cada um com vários casos de uso.

1. Cache::put()

Este método aceita três parâmetros-chave, duration e data a serem armazenados em cache.

Vamos dar uma olhada em como usar Cache::put():

Cache::put(key, data, duration)

$post = Post::find(1);

Cache::put('post_1', $post, 20);

O código acima irá armazenar o post com a chave única por 20 segundos.

2. Cache::putMany()

Este método armazena um conjunto de dados no cache de uma só vez com a mesma duração. Ele aceita dois parâmetros que são data e seconds.

Vamos dar uma olhada em como usar Cache::putMany():

Cache::putMany(data, duration) // syntax

$posts = Post::all();

Cache::putMany($posts, 20);
3. Cache::remember()

Este método é outra excelente forma de implementar a estratégia de cache Aside. O método Cache::remember() aceita três parâmetros, uma keysecondsclosure usados para recuperar dados da base de dados se não forem encontrados.

Vamos dar uma olhada em como usar Cache::remember():

Cache::remember(key, duration, closure) // syntax

Cache::remember('posts', 20, function(){
  return Post::all();
});

O cache do Laravel também tem o método Cache::rememberForever(), que não aceita o parâmetro seconds e armazena o data para sempre.

4. Cache::forever()

Este método armazena os dados no servidor cache para sempre sem especificar qualquer duração. Você pode implementá-lo com o seguinte código:

Cache::forever(key, data)

$post = Post::find(1);

Cache::forever('post_1', $post);

Recuperando dados de cache

Os métodos nesta categoria recuperam os dados de cache. Alguns destes métodos podem comportar-se de forma diferente, dependendo se os dados são encontrados ou não.

1. Cache::get()

Este método recupera dados do servidor de cache com uma chave específica. Você pode recuperar um item usando o código abaixo:

Cache::get(key) // syntax

$posts = Cache::get('posts');
2. Cache::many()

Este método é similar ao Cache::putMany(). Ele é usado para recuperar um array de dados em cache de uma vez usando um array das chaves em cache. Você pode recuperar um array de cache usando o seguinte código:

Cache::many(keys) // syntax

const $keys = [
  'posts',
  'post_1',
  'post_2'
];

$posts = Cache::many($keys);
3. Cache::remember()

Você também pode usar este método para recuperar dados em cache, verificando o servidor de cache usando a chave fornecida. Se os dados estiverem armazenados no cache, ele os recuperará. Caso contrário, ele recuperará os dados do servidor de banco de dados e os armazenará em cache. Este método é o mesmo que o método Cache::rememberForever() com apenas um parâmetro de seconds extra no método Cache::remember().

Remoção de itens do cache

Os métodos sob esta categoria são usados para remover itens de cache, agrupados por funcionalidade.

1. Cache::forget()

Este método remove um único item do cache com um parâmetro-chave especificado:

Cache::forget('key');
2. Cache::flush()

Este método remove um único item do cache com um parâmetro chave especificado:

Cache::flush();

Valores de cache de incremento e desincremento

Você pode ajustar os valores de um valor inteiro armazenado no seu cache usando os métodos de incremento e decremento, respectivamente:

Cache::increment('key');

Cache::increment('key', $amount);

Cache::decrement('key');

Cache::decrement('key', $amount);

O cache do Laravel tem muitos grandes métodos que não discutimos acima, mas os métodos acima são populares. Você pode obter uma visão geral de todos os métodos na documentação oficial do cache do Laravel.

Comandos de cache explicados

Laravel fornece comandos para tornar o trabalho com o cache Laravel fácil e rápido. Abaixo está a lista de todos os comandos e suas funcionalidades.

Limpae o cache do Laravel

Este comando é usado para limpar o cache do Laravel antes mesmo de expirar usando o terminal/console. Por exemplo, você pode executar o seguinte comando:

php artisan cache:clear

Limpar o cache de rotas

Este comando é usado para limpar o cache de rotas do seu aplicativo Laravel. Por exemplo, execute o seguinte comando para limpar o seu cache de rotas:

php artisan config:cache

Excluir arquivos de visualização compilados

Este comando é usado para limpar os arquivos de visualização compilados do seu aplicativo Laravel. Você pode consegui-lo com o seguinte comando:

php artisan view:clear

Tabela do banco de dados

Ao usar o driver do banco de dados, você precisa criar um esquema de banco de dados chamado cache para armazenar os dados do cache. Você também pode usar o comando Artisan para gerar uma migração com o esquema apropriado:

php artisan cache:table

Estratégias de cache do Laravel

Dependendo do caso de uso do seu aplicativo e da estrutura de dados, é provável que várias estratégias de cache diferentes estejam disponíveis para você. Você pode até mesmo criar uma estratégia personalizada para atender às suas necessidades. Abaixo veremos a lista de estratégias de cache populares que você pode implementar em seu projeto Laravel.

writeThrough

Na estratégia writeThrough, o servidor de cache fica entre os pedidos e o servidor de banco de dados, fazendo com que cada operação de gravação passe pelo servidor de cache antes de ir para o servidor de banco de dados. Assim, a estratégia de cache writeThrough é semelhante à estratégia readThrough.

Você pode implementar esta estratégia com o cache do Laravel com o seguinte código:

public function writeThrough($key, $data, $minutes) {
    $cacheData = Cache::put($key, $data, $minutes)

    // Database Server is called from(after) the Cache Server.
    $this->storeToDB($cachedData)
    return $cacheData
}

private function storeToDB($data){
    Database::create($data)
    return true
}

writeBack (writeBehind)

Esta estratégia é uma forma mais avançada de implementar a estratégia writeThrough, acrescentando atrasos nas operações de escrita.

Você também pode chamar isso de estratégia de writeBehind devido ao atraso no tempo aplicado ao servidor de cache antes de escrever os dados para o servidor de banco de dados.

Você pode implementar esta estratégia com o cache do Laravel com o seguinte código:

$durationToFlush = 1; // (in minute)
 $tempDataToFlush = [];

  public function writeBack($key, $data, $minutes){
    return $this->writeThrough($key, $data, $minutes);
  }

  public function writeThrough($key, $data, $minutes) {
      $cacheData = Cache::put($key, $data, $minutes);
      $this->storeForUpdates($cacheData);
      return $cacheData;
  }

// Stores new data to temp Array for updating
  private function storeForUpdates($data){
    $tempData = {};
    $tempData['duration'] = this.getMinutesInMilli();
    $tempData['data'] = data;
    array_push($tempDataToFlush, data);
  }

// Converts minutes to millisecond
private function getMinutesInMilli(){
  $currentDate = now();
  $futureDate = Carbon(Carbon::now()->timestamp + $this->durationToFlush * 60000)
  return $futureDate->timestamp
}

// Calls to update the Database Server.
public function updateDatabaseServer(){
  if($this->tempDataToFlush){
    foreach($this->tempDataToFlush as $index => $obj){
      if($obj->duration timestamp){
        if(Database::create($obj->data)){
            array_splice($this->tempDataToFlush, $index, 1);
        }
      }
    }
  }
}

O método writeBack chama para o método writeThrough, que armazena os dados no servidor de cache e um array temporário para ser empurrado posteriormente para o servidor de banco de dados usando o método updateDatabaseServer. Você pode configurar um CronJob para atualizar o servidor de banco de dados a cada cinco minutos.

writeAround

Esta estratégia permite que todas as operações de escrita vão diretamente para o servidor de banco de dados sem atualizar o servidor de cache – somente durante as operações de leitura é que o servidor de cache é atualizado.

Assumindo que um usuário deseja criar um novo Article, o Articlearmazena diretamente no servidor do banco de dados. Quando o usuário deseja ler o conteúdo do Article pela primeira vez, o Article é recuperado do servidor do banco de dados e atualiza o servidor de cache para solicitações subseqüentes.

Você pode implementar esta estratégia com o cache do Laravel com o seguinte código:

public function writeAround($data) {
    $storedData = Database::create($data);
    return $storedData;
}

public function readOperation($key, $minutes){
    $cacheData = Cache::remember($key, $minutes, function() {
      return Article::all();
    })
    return $cacheData;
}

Cache aside (Carregamento preguiçoso)

Nesta estratégia, o banco de dados é posto de lado e o aplicativo solicita primeiro os dados do servidor de cache. Então, se houver um acerto (encontrado), os dados são devolvidos ao cliente. Caso contrário, se houver um erro (não encontrado), o servidor de banco de dados solicita os dados e atualiza o servidor de cache para solicitações subseqüentes.

Você pode implementar esta estratégia com o cache do Laravel com o seguinte código:

public function lazyLoadingStrategy($key, $minutes, $callback) {
  if (Cache::has($key)) {
      $data = Cache::get($key);
      return $data;
  } else {
      // Database Server is called outside the Cache Server.
      $data = $callback();
      Cache::set($key, $data, $minutes);
      return $data;
  }
}

O código acima mostra a implementação do cache Aside Strategy, que é equivalente à implementação do método Cache::remember.

Read through

Esta estratégia é o oposto direto da estratégia do cache Aside. Nesta estratégia, o Servidor de cache fica entre o Pedido do Cliente e o Servidor de Base de Dados.

As solicitações vão diretamente para o servidor de cache, e o servidor de cache é responsável por recuperar os dados do servidor de banco de dados se não forem encontrados no servidor de cache.

Você pode implementar esta estratégia com o cache do Laravel com o seguinte código:

public function readThrough($key, $minutes) {
      $data = Cache::find($key, $minutes);
      return $data;
}

private function find($key, $minutes){
    if(Cache::has($key);){
      return Cache::get($key);
    }

    // Database Server is called from the Cache Server.
    $DBdata = Database::find($key);
    Cache:put($key, $DBdata, $minutes);
    return $DBdata;
}

Aí está! Agora discutimos algumas estratégias populares de cache para o seu próximo aplicativo Laravel. Lembre-se, você pode até usar uma estratégia de cache personalizada que melhor se adapte aos requisitos do seu projeto.

Cache da interface do usuário (UI) de um aplicativo Laravel

O cache da interface do usuário de um aplicativo Laravel é um conceito conhecido como Full Page Cache (FPC). Este termo se refere ao processo de cache da resposta HTML de um aplicativo.

É excelente para aplicativos onde os dados HTML dinâmicos não mudam com frequência. Você pode fazer o cache da resposta HTML para uma resposta geral e uma renderização mais rápida do HTML.

Nós podemos implementar o FPC com a seguinte linha de código:

class ArticlesController extends Controller {
    public function index() {
        if ( Cache::has('articles_index') ) {
            return Cache::get('articles_index');
        } else {
            $news = News::all();
            $cachedData = view('articles.index')->with('articles', $news)->render();
            Cache::put('articles_index', $cachedData);                                         
            return $cachedData;           
        }  
    }
}

À primeira vista, você deve ter notado que nós verificamos se essa página de articles_index já existe no nosso servidor cache. Então retornamos a página renderizando-a com os métodos view() e render() do Laravel.

Caso contrário, nós renderizamos a página e armazenamos a saída no nosso servidor de cache para pedidos subsequentes antes de devolver a página renderizada ao navegador.

Construir um aplicativo Laravel

Agora vamos aplicar o que aprendemos até agora, criando um novo projeto Laravel e implementando o cache Laravel.

Se você ainda não usou Laravel, você pode ler o que Laravel é e ver a nossa lista de excelentes tutoriais de Laravel para começar.

Configurando o Laravel

Primeiro, vamos criar uma nova instância de Laravel usando o comando abaixo. Você pode consultar a documentação oficial para mais informações.

Abra seu console e navegue até onde você armazena seus projetos PHP antes de executar os comandos abaixo. Certifique-se de ter o Composer instalado e configurado corretamente.

composer create-project laravel/laravel fast-blog-app

// Change directory to current Laravel installation
cd fast-blog-app

// Start Laravel development server.
php artisan serve

Configuração e alimentação do banco de dados

Em seguida, criaremos nossa base de dados, em um novo modelo de Article e semearemos 500 pontos de dados falsos para testes.

Abra o seu cliente de base de dados e crie uma nova base de dados. Faremos o mesmo com o nome fast_blog_app_db e então preencheremos nosso arquivo .env com as informações de identificação do banco de dados:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=fast_blog_app_db
DB_USERNAME=//DB USERNAME HERE
DB_PASSWORD=//DB PASSWORD HERE

A seguir, vamos executar o seguinte comando para criar a migração e o modelo de Article simultaneamente:

php artisan make:model Article -m

Abra o database/migrations/xxx-create-articles-xxx.php e cole no seguinte código:

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('description');
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

A seguir, execute o comando abaixo para criar um novo seeder:

php artisan make:seeder ArticleSeeder

Abra o arquivo seeder recém-criado encontrado em database/seeders/ArticleSeeder.php e cole no código a seguir:

<?php
namespace Database\Seeders;
use App\Models\Article;
use Illuminate\Database\Seeder;
class ArticleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Article::factory()->count(500)->create();
    }
}

Abra o arquivo DatabaseSeeder.php no mesmo diretório e adicione o seguinte código:

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(ArticleSeeder::class);
    }
}

A seguir, execute o comando abaixo para criar uma nova fábrica:

php artisan make:factory ArticleFactory

Abra o arquivo de fábrica recém-construído encontrado em database/factories/ArticleFactory.php e cole no seguinte código:

<?php
namespace Database\Factories;
use App\Models\Article;
use Illuminate\Database\Eloquent\Factories\Factory;
class ArticleFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Article::class;
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'title' => $this->faker->text(),
            'description' => $this->faker->paragraph(20)
        ];
    }
}

Agora, execute o comando abaixo para migrar o nosso schema recém-criado e também semear os nossos dados falsos para testes:

php artisan migrate --seed

Criar o controlador de artigos

Em seguida, vamos criar o nosso controlador e configurar as nossas rotas para lidar com o nosso pedido e recuperar os dados usando o modelo acima.

Execute o seguinte comando para criar um novo ArticlesController dentro da pasta app/Http/Controllers :

php artisan make:controller ArticlesController --resource

Abra o arquivo e adicione o seguinte código à classe:

// Returns all 500 articles with Caching
public function index() {
  return Cache::remember('articles', 60, function () {
      return Article::all();
  });
}

// Returns all 500 without Caching 
public function allWithoutCache() {
  return Article::all();
}

Depois disso, abra o arquivo api.php encontrado dentro das routes/ pasta e cole no código a seguir para criar um endpoint que possamos chamar para recuperar nossos dados:

Route::get('/articles', 'ArticlesController@index');

Route::get('/articles/withoutcache', 'ArticlesController@allWithoutcache');

Testando o desempenho

Finalmente, vamos testar o desempenho da resposta do nosso aplicativo com ou sem a implementação do cache Laravel.

Esta captura de tela mostra o tempo de resposta do API com cache implementado:

Tempo de resposta Laravel API com cache.
Tempo de resposta Laravel API com cache.

A captura de tela a seguir mostra o tempo de resposta do API sem cache implementado – note que o tempo de resposta aumentou sobre a instância em cache em mais de 5.000%:

Tempo de resposta Laravel API sem cache.
Tempo de resposta Laravel API sem cache.

Resumo

Exploramos várias estratégias para implementar e manipular o cache do Laravel, construindo um novo projeto, comparando as suas respostas e comparando os resultados.

Você também aprendeu a usar os diferentes métodos e drivers de cache do Laravel. Além disso, implementamos diferentes estratégias de cache para ajudá-lo a descobrir qual delas pode ser a mais adequada para você.

Para saber mais sobre o Laravel, explore nossa seleção dos melhores tutoriais do Laravel escolhidos a dedo. Seja você um iniciante ou um desenvolvedor avançado do Laravel, sempre há algo para todos!

Se você ainda tiver dúvidas sobre o cache do Laravel, por favor nos avise na seção de comentários.

Solomon Eseme

I am a Software Engineer and Content Creator who is geared toward building high-performing and innovative products following best practices and industry standards. I also love writing about it at Masteringbackend.com. Follow me on Twitter, LinkedIn, and About Me