Einführung
Ich lerne kürzlich THinkPHP 5.1 und nachdem ich die Funktionsweise der Cache-Methode gesehen habe, bin ich etwas verwirrt. Obwohl es viele Methoden kapselt und sehr bequem zu verwenden ist, scheint es für fortgeschrittene Operationen von Redis nicht sehr geeignet zu sein. Zu Lernzwecken wurde der Quellcode leicht geändert. Zunächst möchte ich zwei Punkte anmerken: Erstens ist diese Änderung nur eine persönliche Meinung und nicht für jedermann geeignet. Zweitens dient diese Änderung nur zum Lernen. Bitte seien Sie vorsichtig, wenn Sie den Quellcode ändern. Frage
Beim Üben von Redis habe ich festgestellt, dass Sie, wenn Sie erweiterte Methoden wie hSet
, hGet
usw. verwenden möchten, zuerst das Handle zurückgeben müssen ausführen. Wie Sie unten sehen können
<?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) } }
, war die Ausführung erfolgreich. Die Frage ist, warum das Handle zuerst zurückgegeben werden soll, was mit der magischen Methode von __call
gelöst werden kann. 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