您好,登錄后才能下訂單哦!
使用laravel的Redis時候亂用Facades踩了一個坑。。。
判斷Redis是否有某個key值得時候是可以這樣寫,
Redis::exists(key值)
因為使用了Redis門面,所以可以直接使用Redis::exists而不用先建立實例,就是文檔中介紹的“Facade 基類使用魔術方法 __callStatic() 從你的門面中調用解析對象”。
簡單說就是沒有exists這個靜態方法,使用的時候會調用__callStatic(),建立實例:
$instance = static::getFacadeRoot();
使用Redis時候沒有使用默認庫0,所以按照文檔上的例子指定服務,
代碼如下:
Redis::connection('users'); Redis::exists(key值)
這么做不能判斷key值是否存在,測試以后發現第二行Redis::exists連接的仍然是默認庫0。
亂用Facades踩到坑了!
我用的是laravel5.2,redis使用Predis。
雖然Redis的Facades是一個靜態代理,在使用時候"Redis::"也是靜態唯一的,BUT connection并不是一個靜態方法。
Redis對應的Facades底層類 Illuminate\Redis\Database,connection方法如下
/** * Get a specific Redis connection instance. * * @param string $name * @return \Predis\ClientInterface|null */ public function connection($name = 'default') { return Arr::get($this->clients, $name ?: 'default'); }
返回redis的鏈接實例。
實際上$this->clients在Redis::調用__callStatic()建立實例的時候就已經初始化,
/** * Create a new Redis connection instance. * * @param array $servers * @return void */ public function __construct(array $servers = []) { $cluster = Arr::pull($servers, 'cluster'); $options = (array) Arr::pull($servers, 'options'); if ($cluster) { $this->clients = $this->createAggregateClient($servers, $options); } else { $this->clients = $this->createSingleClients($servers, $options); } }
打印發現 $this->clients 是將 redis的所有配置都初始化,當connection傳入配置名的時候選擇這個配置鏈接實例。
雖然Redis實例是靜態的,但是這個redis鏈接并不是。
Redis::exists()更是和connection()方法無關,redis門面調用__callStatic()后會執行 Illuminate\Redis\Database 的exists方法,但是Database沒有這個方法,所以觸發__call()方法。
/** * Dynamically make a Redis command. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->command($method, $parameters); }
而command() 方法使用的是default配置,也就是說Redis::所有方法除了connection都是默認庫。
/** * Run a command against the Redis database. * * @param string $method * @param array $parameters * @return mixed */ public function command($method, array $parameters = []) { return call_user_func_array([$this->clients['default'], $method], $parameters); }
所以要使用非默認配置的同一個redis鏈接時候必須保存redis實例,
$redis = Redis::connection("user"); $redis->exists(key值);
$redis->exists 不會調用database的command方法,redis繼續使用connection選擇的初始化鏈接,不會選擇default配置。
這其實還涉及到Predis底層的實現,已經超出我的理解范圍。
看完代碼感覺還是有點暈。。。
反正Redis門面還是不要亂用。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。