【问题标题】:Laravel 5: Model object could call Builder method. How does Laravel do that?Laravel 5:模型对象可以调用 Builder 方法。 Laravel 是如何做到这一点的?
【发布时间】:2016-04-04 11:28:20
【问题描述】:

在 Laravel 包中,模型 User 派生自 Model 类。 虽然 Model 类没有“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是派生自Model类,但是Model类没有“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;

【问题讨论】:

    标签: php laravel laravel-5 eloquent query-builder


    【解决方案1】:

    $user = Users::find($id); 返回 eloquent 用户模型或 null。所以你不能在它上面使用'join',因为它不是一个构建器对象。

    $user = Users::whereId($id); 将返回一个查询生成器,因此您可以在其上使用“加入”。

    或者,你可以这样写 -

    $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();
    

    【讨论】:

      【解决方案2】:

      这是因为 Eloquent 在幕后使用了 Illuminate\Database\Query\Builder,您可以在 Builder 类中找到所有这些方法。

      在这种情况下,当您运行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 方法返回new Builder($query); 所以它是一个Illuminate\Database\Query\Builder 对象

      【讨论】:

      • 谢谢!很有帮助!
      猜你喜欢
      • 1970-01-01
      • 2012-12-21
      • 2019-02-12
      • 1970-01-01
      • 2020-10-26
      • 1970-01-01
      • 2020-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多