当试图从Laravel的Redis中获取不存在的键时,会返回null值的情况
这是一个让人开心的世界,会返回false或者null。
假设
行动环境
-
- Laradock
Laravel 6.12
Redis 5.0.3
phpredis 5.1.1
数据库的内容
假设 Redis 中只有一个键名为 key1 的键存在。
127.0.0.1:6379> SET key1 value1
OK
127.0.0.1:6379> KEYS *
1) "key1"
请简洁总结。
Redis 可以被描述为一种内存数据结构存储系统。
当在Redis中指定一个不存在的键时,会返回nil。
127.0.0.1:6379> GET key1
"value1"
127.0.0.1:6379> GET key2
(nil)
PhpRedis: PHP扩展之一
在PhpRedis中,返回的是布尔类型的false。
$redis = new Redis();
$redis->connect('redis', 6379);
$value = $redis->get('key2');
var_dump($value);
string(6) "value1"
bool(false)
Laravel 框架
如果在 Laravel 中使用 PhpRedis 连接到 Redis 时,会返回 null 类型的 null。
use Illuminate\Support\Facades\Redis;
Redis::set('key1', 'value1');
$value = Redis::get('key1'); //--> "value1"
$value = Redis::get('key2'); //--> null
解释
Redis (中文:缓存数据库)
当使用 Redis 的 GET 或 MGET 命令获取不存在的键时,将返回 nil。
可以将字符串”nil”设置为SET,但不能设置特殊值nil。
127.0.0.1:6379> GET key2
(nil)
127.0.0.1:6379> SET key3 nil
OK
127.0.0.1:6379> GET key3
"nil"
PhpRedis是一个用于PHP的Redis扩展。
使用PhpRedis的get或mget方法尝试获取不存在的键时,将返回布尔类型的false。
这一点也在官方文件中明确指出。
返回值
字符串或布尔型:如果键不存在,则返回 FALSE。否则,返回与该键关联的值。
然而,请务必在这里记住的是,在PHP中,”0″或空字符串与false被视为相等的。
// 値として "0" をセットしてみる。
$redis->set('key4', 0);
$val4 = $redis->get('key4');
// キーの存在チェックのつもり...
if (!$val4) {
echo "key4は存在しない";
}
// 値として空文字をセットしてみる。
$redis->set('key5', "");
$val5 = $redis->get('key5');
// これもキーの存在チェックのつもり...
if (!$val5) {
echo "key5は存在しない";
}
那么,结果怎么样呢?
key4は存在しない
key5は存在しない
要阻止这种情况发生,只有使用严格比较运算符。
// 正しいキーの存在チェック
if ($val4 === false) {
echo "key4は存在しない";
}
Laravel是一个原生的PHP框架。
好了,终于进入正题了。
在Laravel中,可以使用PhpRedis来访问Redis。
由于使用了PhpRedis,所以get()和mget()可能会返回false,但实际上返回的是null。
该原因可以在Illuminate\Redis\Connections\PhpRedisConnection.php文件中找到。
public function get($key)
{
$result = $this->command('get', [$key]);
return $result !== false ? $result : null;
}
public function mget(array $keys)
{
return array_map(function ($value) {
return $value !== false ? $value : null;
}, $this->command('mget', [$keys]));
}
我们可以明显看出,它在专门检查获取的值是否为false,如果为false则返回null。
为什么要做这么麻烦的事情呢?
以前,由于使用PhpRedis返回false而导致缓存相关的错误发生。因此,似乎已经修改为返回null。
印象
仅使用Laravel访问Redis并使用PhpRedis,并不意味着会得到与PhpRedis相同的结果。
如果用一位開發者的評論來擬仿時,當修正錯誤時可能會這樣說:
我们使用 Laravel,而不是直接使用 PhpRedis。
那大概就是这样了吧。
请参考
-
- Laravel 公式ドキュメント
Redis
PHP 公式ドキュメント
型の比較表
PhpRedis
Why does GET/MGET return false instead of null for non-existent keys?
同様の違和感を感じる人は多いみたいですが、破壊的変更になるため却下されたようです。
返回 null 本身并没有关系,但没有在文档中说明这一点让我有点不友好的感觉。如果被告知要看框架的源代码才能明白的话,那就算了吧…