欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

DB Facade 中的 select 方法分解

程序员文章站 2024-02-07 21:18:10
...

前言

Laravel 框架中的查询构造器相当的强大,可能是我的基础太差。当我看到 DB Facade 中的 select 方法时一时不能理解,于是就有了这篇文章。

select()方法的2种使用

1. 链式调用:

$users = DB::table('users')->select('uname, realname')->get(); 

通过 Laravel Debugbar 上面这句代码执行的SQL是:

select `uname`, `realname` from `users` 

2. 静态调用:

$sql = "select uname, realname from users";$users = DB::select($sql); 

这种方式,执行的SQL语句跟链式调用执行语句是一样的。

分解

据其文档描述table()会针对指定的数据表返回一个查询构造器实例,追踪到 DB Facade 类中

--文件位置 framework/src/Illuminate/Support/Facades/DB.php namespace Illuminate\Support\Facades;/*** @see \Illuminate\Database\DatabaseManager* @see \Illuminate\Database\Connection*/class DB extends Facade{    /**     * Get the registered name of the component.     *     * @return string     */    protected static function getFacadeAccessor()    {        return 'db';    }} 

这个文件中根本没有table()这个静态方法,但是这个类继承了 Facade 这个类

Laravel 中的 Facades

Laravel Facade 是一种为容器内部服务提供类型静态接口的类。据其文档描述,Facades 是可触及容器服务底层实现方式的代理。使用 facade 类的好处是让开发者使用服务是更加便捷。

Facade 类中包含一个名为 $app的私有属性,其值为服务容器的引用。

__callStatic魔术方法用于处理实际并不存在的静态方法的调用。因为 Facade 类并未实现该方法。因此,__callStatic 会从容器获取各自的服务,进而调用。

__callStatic 方法具体实现:

--!文件位置 framework/src/Illuminate/Support/Facades/Facade.php /**+ Handle dynamic, static calls to the object.*+ @param  string  $method+ @param  array   $args+ @return mixed*/public static function __callStatic($method, $args){    $instance = static::getFacadeRoot();    if (! $instance) {        throw new RuntimeException('A facade root has not been set.');    }    switch (count($args)) {        case 0:            return $instance->$method();        case 1:            return $instance->$method($args[0]);        case 2:            return $instance->$method($args[0], $args[1]);        case 3:            return $instance->$method($args[0], $args[1], $args[2]);        case 4:            return $instance->$method($args[0], $args[1], $args[2], $args[3]);        default:            return call_user_func_array([$instance, $method], $args);    }} 

通过 $instance = static::getFacadeRoot()来得到调用该方法的所属实例

public static function getFacadeRoot(){    return static::resolveFacadeInstance(static::getFacadeAccessor());} 

在 DB Facade中 已实现 getFacadeAccessor()该方法 return 'db'。

protected static function resolveFacadeInstance($name){  if (is_object($name)) {      return $name;  }  if (isset(static::$resolvedInstance[$name])) {      return static::$resolvedInstance[$name];  }  return static::$resolvedInstance[$name] = static::$app[$name];} 

通过 __callStatic() 及 static::后期静态绑定。实现了这个伪静态的调用。这也就明白了为什么可以通过静态方法调用DB::select()。

我们再回到第一种调用方式:

--文件位置 #Illuminate\Database\Querypublic function select($colums = ['*']){    $this->columns = is_array($columns) ? $columns : func_get_args();    return $this;} 

通过源码可以看出 select 是个可变参数函数,默认接收一个数组。

总结

通过对 select 的分解,我们也可知道其他 Facades 中方法的运作原理。