Laravel 用户模型条件预加载(有)
Laravel user model conditional eager loading (with)
我正在使用 Laravel 和 Vue 构建混合应用程序。
我有一个用例,其中并非所有用户都有特定关系。例如,客户可以有一个 域 和多个 业务单位 。
目前我是这样设置的:
<?php
namespace App\Models;
use Laravel\Sanctum\HasApiTokens;
use Spatie\MediaLibrary\HasMedia;
use Illuminate\Notifications\Notifiable;
use Lab404\Impersonate\Models\Impersonate;
use Spatie\MediaLibrary\InteractsWithMedia;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements HasMedia
{
use Traits\BaseModelTrait;
use Traits\ActiveTrait;
use InteractsWithMedia;
use Impersonate;
use HasApiTokens;
use Notifiable;
use HasFactory;
protected $hidden = [
'password', 'remember_token',
];
protected $fillable = [
'name', 'email', 'password', 'avatar',
];
protected $casts = [
'settings' => AsArrayObject::class,
'is_admin' => 'boolean',
];
protected $with = [
'domain',
'BusinessUnits'
];
public function scopeAdmin($query)
{
return $query->where('is_admin', true);
}
public function scopeEmployee($query)
{
return $query->whereNull('domain_id');
}
public function scopeClient($query)
{
return $query->whereNotNull('domain_id');
}
public function BusinessUnits()
{
return $this->belongsToMany(BusinessUnit::class, 'users_business_units_pivot');
}
public function Domain()
{
return $this->belongsTo(Domain::class);
}
}
这种方法的“问题”在于,对于每个请求,每个用户都会执行 2 个查询。我希望仅当“domain_id”不为空(scopeClient)时才加载关系。
对于普通的“模型”,我可以 select 每页应该加载哪些模型等,但是对于经过身份验证的用户来说,这实际上是不可能的。
我想我正在寻找这样的东西:
protected $with = [
(!$this->domain_id) ? 'domain' : null,
(!$this->domain_id) ? 'BusinessUnits' : null
];
这当前会生成一个错误:“常量表达式包含无效操作。”
任何解决此问题的建议和/或想法将不胜感激!
要获取所有拥有域的用户,请使用 whereHas()
$users = User::whereHas('Domain')->with(['Domain', 'BusinessUnits'])->get();
它将发起 3 个查询,一个针对用户,一个针对域,一个针对业务单位。
您可以尝试使用事件:
// this code should be inside your model
public static function boot()
{
parent::boot();
self::retrieved(function($model){
if($model->domain_id !== null)
{
$model->load('domain', 'BusinessUnits');
}
});
}
显然,您必须从 $with
中删除这些关系
我正在使用 Laravel 和 Vue 构建混合应用程序。 我有一个用例,其中并非所有用户都有特定关系。例如,客户可以有一个 域 和多个 业务单位 。
目前我是这样设置的:
<?php
namespace App\Models;
use Laravel\Sanctum\HasApiTokens;
use Spatie\MediaLibrary\HasMedia;
use Illuminate\Notifications\Notifiable;
use Lab404\Impersonate\Models\Impersonate;
use Spatie\MediaLibrary\InteractsWithMedia;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements HasMedia
{
use Traits\BaseModelTrait;
use Traits\ActiveTrait;
use InteractsWithMedia;
use Impersonate;
use HasApiTokens;
use Notifiable;
use HasFactory;
protected $hidden = [
'password', 'remember_token',
];
protected $fillable = [
'name', 'email', 'password', 'avatar',
];
protected $casts = [
'settings' => AsArrayObject::class,
'is_admin' => 'boolean',
];
protected $with = [
'domain',
'BusinessUnits'
];
public function scopeAdmin($query)
{
return $query->where('is_admin', true);
}
public function scopeEmployee($query)
{
return $query->whereNull('domain_id');
}
public function scopeClient($query)
{
return $query->whereNotNull('domain_id');
}
public function BusinessUnits()
{
return $this->belongsToMany(BusinessUnit::class, 'users_business_units_pivot');
}
public function Domain()
{
return $this->belongsTo(Domain::class);
}
}
这种方法的“问题”在于,对于每个请求,每个用户都会执行 2 个查询。我希望仅当“domain_id”不为空(scopeClient)时才加载关系。 对于普通的“模型”,我可以 select 每页应该加载哪些模型等,但是对于经过身份验证的用户来说,这实际上是不可能的。
我想我正在寻找这样的东西:
protected $with = [
(!$this->domain_id) ? 'domain' : null,
(!$this->domain_id) ? 'BusinessUnits' : null
];
这当前会生成一个错误:“常量表达式包含无效操作。”
任何解决此问题的建议和/或想法将不胜感激!
要获取所有拥有域的用户,请使用 whereHas()
$users = User::whereHas('Domain')->with(['Domain', 'BusinessUnits'])->get();
它将发起 3 个查询,一个针对用户,一个针对域,一个针对业务单位。
您可以尝试使用事件:
// this code should be inside your model
public static function boot()
{
parent::boot();
self::retrieved(function($model){
if($model->domain_id !== null)
{
$model->load('domain', 'BusinessUnits');
}
});
}
显然,您必须从 $with