2回目以降の表示速度をあげる(Laravel)

この前同期の人に教えてもらったちょっといいなと思った内容で、例えばWEBアプリの一覧ページにデータを表示する処理があった時に、毎回データ取得の処理を実行して一覧画面を表示させるとその分クエリを毎回発行して表示するのに多少の時間がかかってしまう場合とかにすごい便利だなと思ったのでメモ的な感じで記事にしてみました。

class IndexController extends Controller
{
    public function index()
    {
        $books = Book::join('book_order', 'books.id', '=', 'book_order.book_id')
                ->join('orders', 'book_order.order_id', '=', 'orders.id') 
                ->selectRaw('books.*, SUM(book_order.quanitiy) AS books_sold')
                ->whereBetween('orders.created_at', [
                    now()->subDays(30)->format('Y-m-d') . '00-00-00',
                    now()->subDays()->format('Y-m-d') . '23:59:59'
                ])
                ->groupBy('books > id')
                ->orderBy('books_sold', 'desc')
                ->take(4)
                ->get();
                
        return view('index', compact('books'));   
    }
}

例えば上記のようなコードがあったとして、viewのindexを表示させるタイミングで毎回上記の処理を実行しクエリを発行すると毎回時間が多少かかってしまいます。(処理の内容は今回は関係ないです。)

では以下のように処理を書き換えてみます。

class indexController extends Controller
{
    public function index()
    {
       $books = cache()->remember('homepage-books', 60*60*24, function() {
               return Book::join('book_order', 'books.id', '=', 'book_order.book_id')
                   ->join('orders', 'book_order.order_id', '=', 'orders.id')
                   ->selectRaw('books.*', SUM(book_order.quantity) AS books_sold)
                   ->whereBetween('order.created_at', [
                       now()->subDays(30)->format('Y-m-d') . '00:00:00',
                       now()->subDay()->format('Y-m-d') . '23:59:59'
                   ])
                   ->groupBy('books.id')
                   ->orderBy('books_sold',  'desc')
                   ->take(4)
                   ->get();
       });
       
       return view('index', compact('books'));
    }
}

上記のコードでは、変数$booksに取得した値を格納する際に、cache()->remember('homepage-books', 60*60*24, function() { 処理 }); のような形で処理を記述しています。  
記述例としてはこんな感じになります。

cache()->remember(' キー ', ' 保有時間 ', ' クロージャ ');

第一引数で指定したキーのキャッシュがあればそれを返し、無ければ第三引数のクロージャを実行し、第二引数の指定の分数分キャッシュします。
上の実行例では、remember()の第二引数に60*60*24で一日間キャッシュを登録しているので、1日であればindexを実行しページを展開する際にクエリを発行せずにキャッシュから取り出した値を表示できます。

なので、60*60で設定しておけば、一時間置きにページを表示した際にキャッシュへデータが登録されるようになります。

今回の記事はちょっと短いですが、データをキャッシュに閉じ込めて再度表示した際にそのデータを使用することでクエリを発行せずキャッシュ内のデータを使用するような実装を書いてみました。

結構webアプリケーションは表示する速度大事になると思うので覚えて置きたいですね。

この記事が気に入ったらサポートをしてみませんか?