如何实现thinkphp中Db类的方法调用风格?
例如:Db::table("table_name")->where("id=10")->find();
我发现Db类中有@method Query where() 请问有什么必然联系吗? 展开
我们先来看下官网对listen的说明:如果开启数据库的调试模式的话,你可以对数据库执行的任何SQL操作进行监听。这无疑很方便我们进行增删改查的调试,以及通过执行的时间进行有效的sql优化,
友情提示:数据库监听要写在执行sql语句的前面,因为只有在调用Db::listen之后的SQL语句才会被监听,调用之前的语句不会被监听。至于为什么我们后面讲!
使用如下方法:
123456Db::listen(function($sql, $time, $explain){ // 记录SQL echo $sql. ' ['.$time.'s]'; // 查看性能分析结果 dump($explain);});有很多小伙伴疑问该方法应该放在哪里?使用之后为什么没有效果,很可能就是提示上所说的那样了,那么接下来我们简单分析一下这个方法!
1、从Db::listen(),可以看出listen是Db中的一个静态方法,那么我们就去找db类
2、从Db类中没有找到该方法,但是我们从use think\db\Connection可以看出,引入了Connection类,我们在这个类找一下这个方法!
12345678910/** * 监听SQL执行 * @access public * @param callable $callback 回调方法 * @return void */public function listen($callback){ self::$event[] = $callback;}3、event 保存我们传入的回调方法
4、在看下面这2个方法
5、当我们执行了sql语句,就会触发会调用debug方法将执行日志写入日志文件中,同事调用trigger方法,如果我们最开始已经传入了回调方法,也就是
1self::$event不为空,(说明我们在执行sql语句之前就已经设置了监听)我们将调用我们的回调函数!
1call_user_func_array总结:在执行sql语句之前我们需要先设置监听,这就是为什么要把Db::listen()写在执行sql语句的前面!
下面我们来看下实际的效果:
效果图:
2019-03-13
<?php
class Db {
private static $link
public static table($table) {
self::$link = 初始化db;
return $this;
}
public function where($params) {
//xxx代码
return $this;
}
public function find($params) {
//xxx代码
return $rows;
}
}
?>
关键在于返回$this指向当前的对象
Db类的 @method 只是用于IDE识别,不是实际代码运行需要的。
这个用法的实现步骤,在Db类中可以看到
class Db
{
...
public static function connect($config = [], $name = false, $query = '')
{
...
}
...
public static function __callStatic($method, $args)
{
return call_user_func_array([static::connect(), $method], $args);
}
}
重点在上面列出的两个方法,__calllStatic 是魔术静态方法,在这个类上做任意方法的静态调用,会走这个方法,并把调用的方法名和参数传进来
类似于php 类的 __get __set __call 等 ,参考 php 魔术方法
然后在 __callStatic 里调用 connect 生成一个Query对象,并把方法名调用到query对象上,然后再返回这个query对象,这样就能进行链式操作了,Query对象中的大部分操作也是返回对象本身(用于链式操作)
至于注释中的 @method 只是告诉ide 哪些方法可以用,写代码的时候不会提示方法不存在
2019-03-06