Introduction
J'apprends THinkPHP 5.1 récemment et lisez-le Le fonctionnement de la méthode Cache est un peu déroutant. Bien qu'il encapsule de nombreuses méthodes et soit très pratique à utiliser, il ne semble pas très convivial pour les opérations avancées de Redis. À des fins d'apprentissage, le code source a été légèrement modifié. Tout d'abord, permettez-moi de souligner deux points : premièrement, cette modification n'est qu'un avis personnel et ne convient pas à tout le monde ; deuxièmement, cette modification est uniquement destinée à l'apprentissage, veuillez être prudent lorsque vous modifiez le code source.
Problème
En pratiquant Redis, j'ai découvert que si vous souhaitez utiliser des méthodes avancées, telles que hSet
, hGet
, etc., vous devez d'abord renvoyer le handle avant de l'exécuter . Comme vous pouvez le voir ci-dessous
<?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) } }
, l'exécution a réussi. La question est de savoir pourquoi la poignée doit être rendue en premier, ce qui peut être résolu avec la méthode magique de __call
.
Tracez le code source
Puisque vous avez des doutes, vous devez les dissiper. En traçant le code source, j'ai vu thinkphp/library/think/cache/Driver.php
et j'ai découvert qu'il n'y avait effectivement pas de __call
, juste handler
pour renvoyer un handle pour exécuter des méthodes avancées. Je ne comprends pas pourquoi __clss
n'est pas utilisé.
Résoudre le problème
La solution est d'ajouter la méthode thinkphp/library/think/cache/Driver.php
dans __call
, afin que non seulement Redis puisse utiliser directement la méthode avancée, mais également d'autres classes Cache qui en héritent Le fichier peut l'utiliser directement. Le code est le suivant
/** * 执行高级方法 * @param $method * @param $parameters * @return mixed */ public function __call($method, $parameters) { return call_user_func_array(array($this->handler(), $method), $parameters); }
Regardez à nouveau le code de test
<?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) } }
Ce problème a été résolu. Quand j'ai terminé la modification, je me suis souvenu que Laravel semblait utiliser __call
, puis j'ai regardé le code source, et c'était bien le cas. Il y a le code suivant dans ravel/vendor/laravel/framework/src/Illuminate/Redis/RedisManager.php
/** * 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); }
Conclusion
En fait, la signification symbolique de cette petite modification est plus grande que la signification pratique. Après tout, ce n'est pas un bug, et. cela peut être réalisé en utilisant handler
. Le plus important pour moi est que lorsque je rencontre des problèmes, je serai plus enclin à vérifier le code source. Plus vous regardez, vos capacités s’amélioreront naturellement.