Laravel学习 - Eloquent\Builder与Query\Builder
在Laravel中出现了两处针对数据库的Builder,一时分不清楚。
Eloquent\Builder
Query\Builder
首先,确认Eloquent\Builder与Query\Builder是否是有继承关系:
1/ 打印两者之间的instanceof关系,发现并没有关系
2/ 查看源码:
Eloquent\Builder的构造器方法中有一个注入参数QueryBuilder
/** * The base query builder instance. * * @var \Illuminate\Database\Query\Builder */ protected $query; /** * Create a new Eloquent query builder instance. * * @param \Illuminate\Database\Query\Builder $query * @return void */ public function __construct(QueryBuilder $query) { $this->query = $query; }
可见两者之间并没有继承的关系,而是Eloquent\Builder采用了代理模式对Query\Builder进行了操作
/** * Dynamically handle calls into the query instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { if ($method === 'macro') { $this->localMacros[$parameters[0]] = $parameters[1]; return; } if (isset($this->localMacros[$method])) { array_unshift($parameters, $this); return $this->localMacros[$method](...$parameters); } if (isset(static::$macros[$method])) { if (static::$macros[$method] instanceof Closure) { return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters); } return call_user_func_array(static::$macros[$method], $parameters); } if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { return $this->callScope([$this->model, $scope], $parameters); } if (in_array($method, $this->passthru)) { return $this->toBase()->{$method}(...$parameters); } $this->forwardCallTo($this->query, $method, $parameters); return $this; }
Eloquent\Builder中的__call方法,在最后也将当前类所有未能定位的方法全部forward到Query\Builder执行。
其次,如何使用Eloquent\Builder,又如何使用Query\Builder呢?
Laravel中既提供了实例的使用,也提供了快捷的Facade使用方法。如:
\Illuminate\Support\Facades\DB::table('user'); // --> object(Illuminate\Database\Query\Builder)
UserModel::query(); // --> object(Illuminate\Database\Eloquent\Builder)
可以看出,使用了Facades\DB得到的是Query\Builder,而在UserModel的query方法调用后得到的是Eloquent\Builder。
个人认为:
1/ DB的方法固然方便,但是更多的将table的信息硬编码,导致后期维护工作量大;
2/ Eloquent\Buidler代理了Query\Builder的方法,因此使用上也与DB的使用差别不大。
在日常的操作中,我们更多的是定义了Model操作类。在Mode类中明确指定了表的名称:
/** * The table associated with the model. * * @var string */ protected $table;
所以,更建议采用Model的方式进行操作。
第三,Eloquent\Builder与Query\Builder得到的结果是否一致呢?
/** * Use Eloquent\Builder * */ $eloquentBuilderResult = User::query()->where('name', 'test')->first(); // var_dump($eloquentBuilderResult); // object(\App\Models\User) {} /** * Use Query\Builder */ $queryBuilderResult = DB::table('user')->where('name', 'test')->first(); // var_dump($queryBuilderResult); // object(\stdClass) {}
因为定义的User对象是继承自\Illuminate\Database\Eloquent\Model(abstract),因此,所有的结果也均为User对象类型。在这一点上,与Yii2的ActiveRecord(User::find)对象非常相似。
而Query\Builder是直接对表数据进行操作,未与对象进行绑定映射关系等,所以在最后的结果呈现上,返回了stdClass的结果对象集。
————————————————
版权声明:本文为CSDN博主「moonmovie」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/moonmovie/article/details/83817436