Introduction
저는 최근 THinkPHP 5.1을 배우고 있는데 Cache 메소드의 동작을 보고 조금 헷갈렸습니다. 많은 메소드를 캡슐화하고 사용하기 매우 편리하지만, Redis의 고급 작업에 그다지 친숙하지는 않은 것 같습니다. 학습을 위해 소스 코드를 약간 수정했습니다. 우선, 두 가지 사항을 선언하고 싶습니다. 첫째, 이 수정 사항은 개인적인 의견일 뿐 모든 사람에게 적합하지 않습니다. 둘째, 이 수정 사항은 학습용이므로 소스 코드를 수정할 때 주의하시기 바랍니다. Question
Redis를 연습하면서 hSet
, hGet
등과 같은 고급 메서드를 사용하려면 먼저 핸들을 반환해야 한다는 것을 알았습니다. 실행. 아래에서 볼 수 있듯이
<?php namespace app\index\controller; use think\cache\driver\Redis; use think\Controller; class RedisTest extends Controller { public function index() { $redis = new Redis(); $redis = $redis->handler(); dump($redis->hSet('h_name', '1', 'tom'));// int(1) } }
실행에 성공했습니다. 문제는 핸들이 먼저 반환되어야 하는 이유인데, 이는 __call
이라는 매직 메서드로 해결할 수 있습니다. hSet
、hGet
等,要先返回句柄,然后才能执行。如下
/** * 执行高级方法 * @param $method * @param $parameters * @return mixed */ public function __call($method, $parameters) { return call_user_func_array(array($this->handler(), $method), $parameters); }
可以看到,执行成功。问题是为什么要先返回句柄,可以用 __call
这种魔术方法来解决的。
追踪源码
既然有了疑惑,就要解惑。追踪着源码,看到 thinkphp/library/think/cache/Driver.php
,发现确实没有 __call
,只是 handler
来返回句柄来执行高级方法。没想明白为什么不用 __clss
。
解决问题
解决方法就是在 thinkphp/library/think/cache/Driver.php
中添加 __call
方法,这样不止 Redis 可以直接使用高级方法,其他继承此文件的 Cache 类都可以直接使用。代码如下
<?php namespace app\index\controller; use think\cache\driver\Redis; use think\Controller; class RedisTest extends Controller { public function index() { $redis = new Redis(); // $redis = $redis->handler(); dump($redis->hSet('h_name', '2', 'jerry'));// int(1) } }
再看下测试代码
/** * Pass methods onto the default Redis connection. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->connection()->{$method}(...$parameters); }
到此问题已解决。当我修改完的时候,想起 Laravel 似乎就是用的 __call
,然后去看了源码,确实如此。在 ravel/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php
中有如下代码
结语
其实这次小修改的象征意义大于实际意义,毕竟这不是什么 bug,使用 handler