藉助查詢引數來利用 Laravel 快取

captain2021發表於2017-04-06

  Laravel 提供了非常直觀和有效的方法來快取你的專案的響應,不論你的專案是什麼(Restful API , web 端或者其他),通常來說,Laravel 可以儲存任何你傳送的(HTML,JSON,集合,Eloquent 例項和其他簡單的)對應你提供的到期時間到快取系統。

  直接使用程式碼,快取一個簡單的響應片段可以是這樣

    return Cache::remember($rememberKey, $minutes , function() use ($data) {
       return $data;
    });

  實際來說也是程式碼看上去的這麼簡單,你可以呼叫記住標記以獲取快取資料,並且可以當它不存在的時候進行快取,傳送 $rememberKey 來標識快取系統中的資料及過期時間(以分鐘為單位)。使用閉包,您可以將資料返回以儲存在快取系統中。他如此簡單以至於開發人員可能不理解一條線上實現所有功能,我們來一步步理清這裡最相關的元素。

  這裡存在幾種使用快取的方法,如 PUT, PULL, GET等,(這裡 有所有方法的詳細),但 remember 方法是你需要的,因為她為你儲存和檢索資料。

  這裡的問題是“ Laravel 如何確定何時儲存資料?”

  為了回答這個問題,我們需要使用關注另一個基本元素“ rememberKey ”,根據 $rememberKey 的值, Laravel 會知道這個資料是否已被快取。所以這裡是這個值的重要性,因為如果你使用相同的 $rememberKey 快取所有的響應,你將在到期時間獲得相同的響應,看上去很明顯不可以這樣不可以?

  不幸的是,對於其他場景來說這不是很明顯。您知道 $rememberKey 的唯一值的重要性,您決定使用當前的 URL ,因此程式碼如下所示:

    $url = request()->url();
    return Cache::remember($url, $minutes, function () use ($data) {
       return $data;
    });

  幾乎相同,但現在 $rememberKey 是當前請求的 URL,這樣你就可以確定記住的金鑰依據請求而有所不同。

  例如,如果您收到請求到此 yourdomain.com/products URL,將使用該確切值來快取響應。每當使用者轉到另一個 URL 時yourdomain.com/categories ,您需要確保快取系統將返回相應的值並相應儲存。

  但是,等一下!我們假設您正在使用查詢引數對結果進行排序或分頁,因此您的網址如下所示:yourdomain.com/products?page=2&sort_by=price 。在這種情況下,當您獲取 URL 時,$url = request()->url() 它不會獲取查詢引數,這意味著由查詢引數引入的響應中的更改不會被反映出來。

  沒問題,你只需要包含查詢引數,一切都會很好,對吧?我們開始做吧。

    $fullUrl = request()->fullUrl();
    return Cache::remember($fullUrl, $minutes, function () use ($data) {
        return $data;
    });

  好的,已經完成了!或不?一點點耐心的我們來做一些測試。如果使用者傳送請求,yourdomain.com/products?page=2&sort_by=price 它將快取資料並返回響應。如果使用者傳送請求 yourdomain.com/products?page=1&sort_by=name ,它將再次快取資料並返回。漂亮!它快取不同的響應並返回它們。現在,最後一次測試。使用者訪問 yourdomain.com/products?page=2&sort_by=price 然後訪問 yourdomain.com/products?sort_by=price&page=2 。這是一個不同的請求,所以快取系統將獨立快取一切,很好!哦,等一下!這是同樣的回應。查詢字串中的順序並不重要,您的專案將返回相同的響應,如果快取系統應該儲存相同的響應,但是它不會返回相同的響應。

  哦,我現在該怎麼辦?看起來解決方案並不像我們開始時那麼簡單。我們需要一種確定方式,獨立於查詢字串的順序,只要它們相同,我們不想再次快取資料。我們需要對查詢字串進行排序。

我們來寫程式碼:

    $url = request()->url();
    $queryParams = request()->query();

    //Sorting query params by key (acts by reference)
    ksort($queryParams);

    //Transforming the query array to query string
    $queryString = http_build_query($queryParams);

    $fullUrl = "{$url}?{$queryString}";

    return Cache::remember($fullUrl, $minutes, function () use ($data) {
        return $data;
    });

  這裡的魔法在哪裡?那麼我們只需使用查詢方法在關聯陣列中獲取查詢引數,然後使用key(而不是值),使用ksort進行排序。ksort 函式作為參考,所以我們不需要再次分配。然後使用查詢引數排序,我們可以再次構建查詢字串,使用http_build_query最終以正確的方式構建 fullUrl ,將其用作要記住的鍵。

  在之後,如果使用者訪問 yourdomain.com/products?sort_by=price&page=2 它將與 yourdomain.com/products?page=2&sort_by=price 允許您快取相同響應相同,即使請求中的URL看起來有所不同。

如果你想要一個“花哨”的解決方案,你甚至可以雜湊fullUrl,就像這樣:

    $url = request()->url();
    $queryParams = request()->query();

    ksort($queryParams);

    $queryString = http_build_query($queryParams);

    $fullUrl = "{$url}?{$queryString}";

    $rememberKey = sha1($fullUrl);

    return Cache::remember($rememberKey, $minutes, function () use ($data) {
        return $data;
    });

翻譯自:https://laravel-news.com/cache-query-param...

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Keep Young, Keep Simple.

相關文章