91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP+Redis緩存的方法是什么

發布時間:2022-01-06 14:26:03 來源:億速云 閱讀:113 作者:iii 欄目:編程語言

本篇內容主要講解“PHP+Redis緩存的方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“PHP+Redis緩存的方法是什么”吧!

有否想過PHP使用redis作為緩存時,如何能:

1.前后臺模塊共用Model層;

2.但是,不能每個Model類都進行緩存,這樣太浪費Redis資源;

3.前后臺模塊可以自由決定從數據庫還是從緩存讀數據;

4.沒有冗余代碼;

5.使用方便。

這里我們先展示實現的最終效果。

馬上安裝使用命令:

$ composer install yeszao/cache

1 最終效果

假設在MVC框架中,model層有一個Book類和一個getById方法,如下:

class Book
{
    public function getById($id)
    {
        return $id;
    }
}

加入緩存技術之后,原來方法的調用方式返回的數據結構都不應該改變。

所以,我們希望,最后的效果應該是這樣的:

(new Book)->getById(100);           // 原始的、不用緩存的調用方式,還是原來的方式,一般是讀取數據庫的數據。
(new Book)->getByIdCache(100);      // 使用緩存的調用方式,緩存鍵名為:app_models_book:getbyid: + md5(參數列表)
(new Book)->getByIdClear(100);      // 刪除這個緩存
(new Book)->getByIdFlush();         // 刪除 getById() 方法對應的所有緩存,即刪除 app_models_book:getbyid:*。這個方法不需要參數。

這樣我們可以很清楚的明白自己在做什么,同時又知道數據的來源函數,并且被引用方式完全統一,可謂一箭三雕。

其實實現起來也比較簡單,就是使用PHP的魔術方法__call()方法。

2 __call()方法

這里簡單說明一下__call方法的作用。

在PHP中,當我們訪問一個不存在的類方法時,就會調用這個類的__call()方法。

(如果類方法不存在,又沒有寫__call()方法,PHP會直接報錯)

假設我們有一個Book類:

class Book
{
    public function __call($name, $arguments)
    {
        echo '類Book不存在方法', $name, PHP_EOL;
    }

    public function getById($id)
    {
        echo '我的ID是', $id, PHP_EOL;
    }
}

當調用存在的getName(50)方法時,程序打印:我的ID是50

而如果調用不存在的getAge()方法時,程序就會執行到A類的__call()方法里面,這里會打印:類Book不存在方法getAge

這就是__call的原理。

3 實現細節

接下來我們就利用__call()方法的這種特性,來實現緩存策略。

從上面的例子,我們看到,__call()方法被調用時,會傳入兩個參數。

  • $name:想要調用的方法名

  • $arguments:參數列表

我們就可以在參數上面做文章。

還是以Book類為例,我們假設其原本結構如下:

class Book
{
    public function __call($name, $arguments)
    {
        // 待填充內容
    }

    public function getById($id)
    {
        return ['id' => $id, 'title' => 'PHP緩存技術' . $id];
    }
}

開始之前,我們還確認Redis的連接,這是緩存必須用到的,這里我們寫個簡單的單例類:

class Common
{
    private static $redis = null;
    
    public static function redis()
    {
        if (self::$redis === null) {
            self::$redis = new \Redis('127.0.0.1');
            self::$redis->connect('redis');
        }
        return self::$redis;
}

然后,我們開始填充__call()方法代碼,具體說明請看注釋:

class Book
{
    public function __call($name, $arguments)
    {
        // 因為我們主要是根據方法名的后綴決定具體操作,
        // 所以如果傳入的 $name 長度小于5,可以直接報錯
        if (strlen($name) < 5) {
            exit('Method does not exist.');
        }

        // 接著,我們截取 $name,獲取原方法和要執行的動作,
        // 是cache、clear還是flush,這里我們取了個巧,動作
        // 的名稱都是5個字符,這樣截取就非常高效。
        $method = substr($name, 0, -5);
        $action = substr($name, -5);

        // 當前調用的類名稱,包括命名空間的名稱
        $class = get_class();

        // 生成緩存鍵名,$arguments稍后再加上
        $key = sprintf('%s:%s:', str_replace('\\', '_', $class), $method);
        // 都用小寫好看點
        $key = strtolower($key);

        switch ($action) {
            case 'Cache':
                // 緩存鍵名加上$arguments
                $key = $key . md5(json_encode($arguments));

                // 從Redis中讀取數據
                $data = Common::redis()->get($key);

                // 如果Redis中有數據
                if ($data !== false) {
                    $decodeData = json_decode($data, JSON_UNESCAPED_UNICODE);
                    // 如果不是JSON格式的數據,直接返回,否則返回json解析后的數據
                    return $decodeData === null ? $data : $decodeData;
                }

                // 如果Redis中沒有數據則繼續往下執行

                // 如果原方法不存在
                if (method_exists($this, $method) === false) {
                    exit('Method does not exist.');
                }

                // 調用原方法獲取數據
                $data = call_user_func_array([$this, $method], $arguments);

                // 保存數據到Redis中以便下次使用
                Common::redis()->set($key, json_encode($data), 3600);

                // 結束執行并返回數據
                return $data;
                break;

            case 'Clear':
                // 緩存鍵名加上$arguments
                $key = $key . md5(json_encode($arguments));
                return Common::redis()->del($key);
                break;

            case 'Flush':
                $key = $key . '*';
                
                // 獲取所有符合 $class:$method:* 規則的緩存鍵名 
                $keys = Common::redis()->keys($key);
                return Common::redis()->del($keys);
                break;

            default:
                exit('Method does not exist.');
        }
    }

    // 其他方法
}

這樣就實現了我們開始時的效果。

4 實際使用時

在實際使用中,我們需要做一些改變,把這一段代碼歸入一個類中,

然后在model層的基類中引用這個類,再傳入Redis句柄、類對象、方法名和參數,

這樣可以降低代碼的耦合,使用起來也更靈活。

完整的代碼已經放在Github上,請參考文章開頭的參考地址。

到此,相信大家對“PHP+Redis緩存的方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

布尔津县| 庐江县| 社会| 乐业县| 封开县| 揭东县| 潮安县| 永城市| 通许县| 社会| 宜宾县| 阿拉善右旗| 惠安县| 海口市| 德昌县| 新津县| 墨江| 丰原市| 昌江| 宣威市| 原阳县| 兰考县| 宝清县| 灵武市| 萨嘎县| 日照市| 朔州市| 大姚县| 泰安市| 金沙县| 抚顺市| 保靖县| 广平县| 巨野县| 轮台县| 自治县| 灌南县| 六枝特区| 临漳县| 南昌市| 老河口市|