欢迎您访问我的笔记本站旨在于记录一些平时工作中遇到的一些问题和解决方法,方便查阅,部分内容来源于网络,如有侵权请联系我删除
  • 微信微信
您现在的位置是:首页 > PHP后端

php __call() 与call_user_func_array()方法结合的使用-[原创]

日期:2018-12-03 14:15:21 作者:tanyi 来源:我的笔记 浏览:1023 次
本文主要是介绍利用标题内两个函数在对redis或其他php扩展类二次封装时的使用

首先我们对redis做一个简单的二次封装,然后来调用里面的方法

namespace Redis;

class Redis{

    private $redis;

    /**
     * Redis constructor.
     */
    public function __construct()
    {
        $this->redis=new \Redis();
        $this->redis->connect('127.0.0.1',6379);
    }
    

    /**
     * 将值添加到在密钥中存储的哈希。如果此值已经在散列中,则返回false。
     * @param $key
     * @param $hashKey
     * @param $value
     * @return int
     */
    public function hSet( $key, $hashKey, $value){
        $re=$this->redis->hSet( $key, $hashKey, $value);
        return $re;
    }

    /**
     * 返回整个哈希,作为字符串索引的字符串数组。
     * @param $key
     * @return array
     */
    public function hGetAll($key){
        $re=$this->redis->hGetAll($key);
        return $re;
    }

}

然后调用这个类里面的方法看是否能正常调用

require_once './Redis/Redis.php';
$redis=new \Redis\Redis();
$redis->hSet('xiaoming','age','18');
$data=$redis->hGetAll('xiaoming');
print_r($data);

打印结果正常输出

image.png

那么我们现在要删除这个键怎么办呢,可以调用del,但是我们类里面没有对这个方法进行二次封装,所以直接调用del肯定会报错,因为redis有很多方法,如果每个方法都在我们的二次封装类里面来封装一次太麻烦,因为很多方法都是可以直接使用,没必要再封装一次,这时我们就可以利用__call($function_name,$args)和mixed call_user_func_array ( callable $callback , array $param_arr )的结合来达到即使我们的类里面没有封装该方法,也可以调用,__call()是一个魔术函数,在调用类里面不存在的方法时会调用该方法,该方法有两个参数,第一个参数 $function_name 会自动接收不存在的方法名,第二个 $args 则以数组的方式接收不存在方法的多个参数。call_user_func_array()方法两个参数,第一参数作为回调方法,第二个参数作为参数传给回调方法,第一个参数可以使数组,用于调用一个类的方法,数组第一个元素为类,第二个元素为类的方法,具体可以自己搜索;下面我们用这两个方法将我们刚封装的redis类改进一下,代码如下

namespace Redis;

class Redis{

    private $redis;

    /**
     * Redis constructor.
     */
    public function __construct()
    {
        $this->redis=new \Redis();
        $this->redis->connect('127.0.0.1',6379);
    }

    /**
     * 调用未封装的方法时直接调用底层方法
     * @param $name
     * @param $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        return call_user_func_array([$this->redis,$name],$arguments);
    }

    /**
     * 将值添加到在密钥中存储的哈希。如果此值已经在散列中,则返回false。
     * @param $key
     * @param $hashKey
     * @param $value
     * @return int
     */
    public function hSet( $key, $hashKey, $value){
        $re=$this->redis->hSet( $key, $hashKey, $value);
        return $re;
    }

    /**
     * 返回整个哈希,作为字符串索引的字符串数组。
     * @param $key
     * @return array
     */
    public function hGetAll($key){
        $re=$this->redis->hGetAll($key);
        return $re;
    }

}

这时我们调用一个我们封装的类里面不存在的方法,看是否成功

require_once './Redis/Redis.php';
$redis=new \Redis\Redis();
//$redis->hSet('xiaoming','age','18');
$a=$redis->del('xiaoming');
var_dump($a);
$data=$redis->hGetAll('xiaoming');
print_r($data);

可以看到del方法并未在二次封装类里面,所以调用时会调用__call方法,然后去调用redis底层的del方法返回结果,而且是有效的,打印结果是删除成功,再次获取xiaoming时已经是空了

image.png

提交评论
评论列表