Laravel 具有预加载关系的模型

Laravel model with preloaded relation

我有一个数据库 table 用于存储我的职位以便不重复它们,并且 Job 模型在内部具有关系,因此当我使用 Eloquent 模型时我必须始终调用或者一遍又一遍地加载 JobTitles 模型。有没有办法始终使用内部预加载 JobTitles 的 Job Model?

    class Job extends Model
    {
        use Notifiable;

        protected $fillable = [ ... ];

        protected $hidden = [
        'token',
        ];


    
        public function title()
        {
            return $this->belongsTo('App\Models\JobTitle','job_title_id');
        }

        public function people()
        {
            return $this->belongsToMany('App\Models\Person','job_person','job_id','person_id');
        }
        
    }

这是 JobTitle 模型

class JobTitle extends Model
{
    use Notifiable;

    protected $table = "job_titles";

    protected $primaryKey = 'job_title_id';

    protected $fillable = [
        'name',
    ];

    protected $hidden = [
    'token',
    ];


    public function jobs()
    {
        return $this->hasMany('App\Models\Job','job_title_id');
    }

    
}

现在我在控制器中的代码如下所示:

 $job = Job::all()->load('title');

它工作正常,但是当我打电话给别人工作时

 $personJobs = Person::find(1)->jobs()->load('title')->get();

给出错误,知道这是如何完成的吗?

当通过方法 $person->jobs() 调用关系时,您最终会得到一个查询生成器,因此您不能像 load() 那样调用模型方法,因为您没有模型的实例.

在得到第一个结果之前调用关系会更有效率(nested eager loading)

$person = Person::with('jobs.title')->find(1);
$personJobs = $person->jobs;

如果您不想从数据库中查询人员数据,您应该使用 whereHas

$personJobs = Job::whereHas('people', function($personQueryBuilder) {
    $personQueryBuilder->where('id',1);
})->with('title')->get();

load() 在查询执行后执行。它被称为 lazy-loading。预加载正在使用 with().

预加载通常比延迟加载快(我在这一点上可能是错的,如果我错了请纠正我)。

此外,使用 jobs() 或任何其他关系,这将 return 关系 object 本身,而通过 ->Jobs 访问它时将执行关系查询并将return一个collection(如果有很多)或模型(如果有一个)。

$personJobs = Person::find(1)->jobs()->load('title')->get(); 不起作用的原因是因为您本质上是在说“作业 hasMany 关系将加载“标题”,但它不起作用,因为 hasMany 没有load() 函数。

所以如果你想解决这个问题,你可以Person::with('jobs.title')->find(1)或者Person::find(1)->load('jobs.title')

始终使用内部预加载 JobTitles 的工作模型。您可以在工作模型中添加 $with 属性:

class Job extends Model
{
   use Notifiable;
   
   protected $with = ['title'];

}