目前使用的是laravel5.1 LTS版本,今天有位同事在想要使用ORM构造这样一个SQL, select * from a where a = 1 and (b = 1 or c = 2)
本人SQL功力很差,不会写复杂的SQL。遇到这样的SQL第一个想法是写原生的SQL,使用DB类。
同事找到了DB::where方法传入闭包,这个我也是知道,但是我觉得使用MODEL类传入闭包的话大概就不行了。
事实证明我错了,
\App\User::where(function($query) {
});
这个是不报错, 在找了一下API发现Laravel的ORM的where方法不支持传入闭包对象。
那么是怎么回事呢。
找源代码吧, 什么问题都可以在源代码中找到答案!
在\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php 代码中根本就没有发现where方法,先不说where传入闭包对象,就说\App\User::where('a', 1) 这种API是怎么实现的。继续找了下源代码, 在代码的最后面发现了两个魔术方法。
__call __callStatic 那么是不是这两个魔术方法起了作用呢。
我在这两个魔术方法里面var_dump()了全部的变量,发现的却是这两的魔术方法起了作用。
截图如下
使用->调用where 方法,传入闭包对象
结果是打印出这样的信息
使用::调用where方法,传入闭包对象
结果是
可以看出来__call __callStatic 发挥了作用。
我去找到了Builder类,找到了where 方法,这个where 可以传入闭包对象,那么orm的where方法传入闭包对象实际是利用了builder类的where方法。
PS:打印使用了DD,我修改了这个function, 使它打印出结果之后不die掉。
PS:在Model类中的__callStatic看到了new static 。 这是一个很重要的使用。可以在上面的截图的结果中看到new static 的结果是\App\User的一个实例, 这是使用静态绑定,目前我也只是理解了一部分,让我去写,是很难做出来的。
PS:PHP中没有函数重载,使用__call __callStatic可以显示伪函数重载。