Laravel 5: 模型对象可以调用生成器方法。 Laravel 是怎么做到的?
Laravel 5: Model object could call Builder method. How does Laravel do that?
在Laravel包中,模型User派生自模型class。
虽然模型 class 没有 "join" 方法,但我仍然可以在用户对象上使用 join 方法。
我不清楚 Laravel 是怎么做到的。
$user = Users::find($id);
$user->
join('GroupMember', 'GroupMember.UserID', '=', 'users.id')->
join('Groups', 'GroupMember.GroupID', '=', 'Groups.GroupID')->
where('users.id','=', $user->id)->get();
以上代码是获取用户的所有相关组。
因为 $user 是从模型 class 派生的,但是模型 class 没有 "join" 方法...
这是用户定义。
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
这是因为 Eloquent 在幕后使用了 Illuminate\Database\Query\Builder
,您可以在 Builder
class.
中找到所有这些方法
当你运行函数在Users
模型中不存在在这种情况下,magic method __call
被使用:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
$query = $this->newQuery();
return call_user_func_array([$query, $method], $parameters);
}
如您在此方法中所见,newQuery
方法已执行。当您查看此方法定义时,您可以在此处看到:
public function newQuery()
{
$builder = $this->newQueryWithoutScopes();
foreach ($this->getGlobalScopes() as $identifier => $scope) {
$builder->withGlobalScope($identifier, $scope);
}
return $builder;
}
此外,当您查看 newQueryWithoutScopes
时,您会看到:
$builder = $this->newEloquentBuilder(
$this->newBaseQueryBuilder()
);
和这个 newEloquentBuilder
方法 returns new Builder($query);
所以它是一个 Illuminate\Database\Query\Builder
对象
$user = Users::find($id);
returns eloquent 用户模型或空。所以你不能在它上面使用 'join' 因为它不是构建器对象。
$user = Users::whereId($id);
将 return 一个查询生成器,因此您可以在上面使用 'join'。
或者你也可以这样写-
$user = Users::find($id);
$user->with([
'GroupMember' => function ($query) {
$query->where('GroupMember.UserID', '=', 'users.id')
},
'Groups' => function ($query) {
$query->where('GroupMember.GroupID', '=', 'Groups.GroupID')
}]),
->where('users.id','=', $user->id)
->get();
在Laravel包中,模型User派生自模型class。 虽然模型 class 没有 "join" 方法,但我仍然可以在用户对象上使用 join 方法。
我不清楚 Laravel 是怎么做到的。
$user = Users::find($id);
$user->
join('GroupMember', 'GroupMember.UserID', '=', 'users.id')->
join('Groups', 'GroupMember.GroupID', '=', 'Groups.GroupID')->
where('users.id','=', $user->id)->get();
以上代码是获取用户的所有相关组。 因为 $user 是从模型 class 派生的,但是模型 class 没有 "join" 方法...
这是用户定义。
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
这是因为 Eloquent 在幕后使用了 Illuminate\Database\Query\Builder
,您可以在 Builder
class.
当你运行函数在Users
模型中不存在在这种情况下,magic method __call
被使用:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
$query = $this->newQuery();
return call_user_func_array([$query, $method], $parameters);
}
如您在此方法中所见,newQuery
方法已执行。当您查看此方法定义时,您可以在此处看到:
public function newQuery()
{
$builder = $this->newQueryWithoutScopes();
foreach ($this->getGlobalScopes() as $identifier => $scope) {
$builder->withGlobalScope($identifier, $scope);
}
return $builder;
}
此外,当您查看 newQueryWithoutScopes
时,您会看到:
$builder = $this->newEloquentBuilder(
$this->newBaseQueryBuilder()
);
和这个 newEloquentBuilder
方法 returns new Builder($query);
所以它是一个 Illuminate\Database\Query\Builder
对象
$user = Users::find($id);
returns eloquent 用户模型或空。所以你不能在它上面使用 'join' 因为它不是构建器对象。
$user = Users::whereId($id);
将 return 一个查询生成器,因此您可以在上面使用 'join'。
或者你也可以这样写-
$user = Users::find($id);
$user->with([
'GroupMember' => function ($query) {
$query->where('GroupMember.UserID', '=', 'users.id')
},
'Groups' => function ($query) {
$query->where('GroupMember.GroupID', '=', 'Groups.GroupID')
}]),
->where('users.id','=', $user->id)
->get();