请教ThinkPHP5源码中的call_user_func_array函数的使用问题

burningx 2019-03-17 07:52:22
今天在写一个类的时候,需要继承到ThinkPHP5 的`think\Db`类,继承它的时候我就顺便读了一下源码,产生了一个知道结果,但是不知道原理的困惑,望各位能帮忙解惑,拜谢,具体如下:

为了方便大家理解,我把`think\Db`类的部分源码给帖上来吧。


<?php

namespace think;

use think\db\Connection;
use think\db\Query;

/**
* Class Db
* @package think
* @method Query table(string $table) static 指定数据表(含前缀)
* @method Query name(string $name) static 指定数据表(不含前缀)
......
*/
class Db
{
......

/**
* 数据库初始化,并取得数据库类实例
* @access public
* @param mixed $config 连接配置
* @param bool|string $name 连接标识 true 强制重新连接
* @return Connection
* @throws Exception
*/
public static function connect($config = [], $name = false)
{
if (false === $name) {
$name = md5(serialize($config));
}

if (true === $name || !isset(self::$instance[$name])) {
// 解析连接参数 支持数组和字符串
$options = self::parseConfig($config);

if (empty($options['type'])) {
throw new \InvalidArgumentException('Undefined db type');
}

$class = false !== strpos($options['type'], '\\') ?
$options['type'] :
'\\think\\db\\connector\\' . ucwords($options['type']);

// 记录初始化信息
if (App::$debug) {
Log::record('[ DB ] INIT ' . $options['type'], 'info');
}

if (true === $name) {
$name = md5(serialize($config));
}

self::$instance[$name] = new $class($options);
}

return self::$instance[$name];
}

......

/**
* 调用驱动类的方法
* @access public
* @param string $method 方法名
* @param array $params 参数
* @return mixed
*/
public static function __callStatic($method, $params)
{
return call_user_func_array([self::connect(), $method], $params);
}
}



我的困惑是,在我们调用Db::name('table');的时候,因为“Db”类没有name()这个静态方法,所以调用了它的魔术方法"__callStatic"。


return call_user_func_array([self::connect(), $method], $params);


上面行代码中的“ call_user_func_array”函数的作用下,调用了类下的“ connect()”我是明白的,但是根据官方文档的解释,我不是很明白为什么会根据“$method”这个变量去调用“think\db\Query”下的 “name”方法去了,“ call_user_func_array”第一个参数传数组的话,不是某个类下的某个方法吗?就算在命名空间的作用下,“think\db\Query”类里面的“name()”方法也不在同一个类上的呀。

不解啊不解。
...全文
803 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
burningx 2019-03-18
  • 打赏
  • 举报
回复
引用 1 楼 下雨的声音丶 的回复:
你要一步一步的跟下去,就豁然开朗了
首先 think\Db类里的 connect静态方法你是知道要调用的,然后你看里面的代码

这里返回了一个(看你配置 这里默认mysql)
think\db\connector\Mysql ,然后是调用的这个类实例的name 静态方法
该类继承了think\db\Connection这个抽象类所以调用了该类下的这些方法

也就证明确实是调用了 think\db\Query”类里面的“name()”方法


也就是说,如果回调静态方法的时候,静态方法里面return一个对象的话,也是属于继承关系?或者说self:: connect()这个方法在最后return think\db\connector\Mysql 对象的时候它本身就已经是“think\db\connector\Mysql”对象了?
下雨的声音丶 2019-03-18
  • 打赏
  • 举报
回复
你要一步一步的跟下去,就豁然开朗了 首先 think\Db类里的 connect静态方法你是知道要调用的,然后你看里面的代码 这里返回了一个(看你配置 这里默认mysql) think\db\connector\Mysql ,然后是调用的这个类实例的name 静态方法 该类继承了think\db\Connection这个抽象类所以调用了该类下的这些方法 也就证明确实是调用了 think\db\Query”类里面的“name()”方法
下雨的声音丶 2019-03-18
  • 打赏
  • 举报
回复
你就不能认真看一下这个代码么 还有 “return一个对象的话,也是属于继承关系” 这句话我可没说过

4,251

社区成员

发帖
与我相关
我的任务
社区描述
国内外优秀PHP框架讨论学习
社区管理员
  • Framework
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧