Laravel 通过属性获得雄辩的查询构建器关系
Posted
技术标签:
【中文标题】Laravel 通过属性获得雄辩的查询构建器关系【英文标题】:Laravel get eloquent query builder relations by property 【发布时间】:2021-12-02 22:49:42 【问题描述】:我正在使用 eloquent 查询构建器根据用户搜索查询提供的参数有条件地构建搜索查询。
这似乎适用于直接属于我正在搜索的模型的属性。但是,在尝试返回与模型相关但不直接属于模型的其他结果时,我遇到了问题。
我到底想做什么:
我正在尝试允许用户按教师姓名搜索学校,其中姓名/关键字通过中间表出现在学校的关系中。
这是我的模型和关系:
学校:
class School extends Authenticatable
protected $fillable = [
'school_name', 'head_teacher', 'address'
];
public function teachers()
return $this->belongsToMany(Teacher::class, 'teacher_links', 'school_id', 'teacher_id');
老师:
class Teacher extends Authenticatable
use Notifiable;
protected $table = 'teacher';
protected $fillable = [
'name'
];
TeacherLink:
class TeacherLink extends Authenticatable
protected $table = 'teacher_links';
protected $fillable = [
'teacher_id', 'school_id'
];
我可以使用$school->teachers
成功地通过控制器中的学校查询教师,所以我知道这种关系运作良好。
这是我的控制器代码,其中用户搜索参数是有条件地建立的:
public function index(Request $request)
$schools = School::query();
// User Search Term
$search = $request->get('search');
$headTeacher = $request->get('head_teacher');
$questions
->when($search, function ($q) use ($search)
$q->where('school_name', 'like', '%' . $search . '%')
->orWhere('head_teacher', 'like', '%' . $search . '%')
// This is the query i'm having an issue with
->whereHas('teachers', function($q) use ($search)
$q->where('teacher_name', 'like', '%' . $search . '%');
);
)
当通过学校名称或 head_teacher 搜索时,两个初始 where 子句返回正确的结果,因为这两个属性直接属于学校。但是,我想通过关系返回包含教师姓名的其他学校。
所以一所学校可以通过中间的teacher_link表属于许多老师,反之亦然,但我不知道如何使用雄辩的查询构建器准确过滤这个。
最初我尝试使用联合函数和连接,它有效但破坏了后续的 where 子句,因为它似乎不允许在联合查询之后跟随 where 子句。
如果有人能告诉我我做错了什么以及如何修复相关查询,那就太好了:
// This is the query i'm having an issue with
->whereHas('teachers', function($q) use ($search)
$q->where('teacher_name', 'like', '%' . $search . '%');
);
编辑
我尝试了以下似乎可行但速度很慢的方法:
$schools
->when($search, function ($q) use ($search)
$q->join("teacher_links", function ($join)
$join->on("teacher_links.school_id", "=", "schools.id");
)
->join("teachers", function ($join)
$join->on("teachers.id", "=", "teacher_links.teacher_id");
)
->select("schools.*")
->where("teachers.teacher_name", 'like', '%' . $search . '%')
->orWhere('school_name', 'like', '%' . $search . '%')
->orWhere('school_address', 'like', '%' . $search . '%')
->orWhere('school_focus', 'like', '%' . $search . '%');
);
【问题讨论】:
whereHas
编译为AND WHERE EXISTS
。也许你正在寻找orWhereHas
(OR WHERE EXISTS
)
【参考方案1】:
尝试在该查询中使用orWhereHas
。
->when($search, function ($q) use ($search)
$q->where('school_name', 'like', '%' . $search . '%')
->orWhere('head_teacher', 'like', '%' . $search . '%')
->orWhereHas('teachers', function ($sub) use ($search)
$sub->where('teacher_name', 'like', '%' . $search . '%');
);
);
【讨论】:
【参考方案2】:尝试使用雄辩的关系
School::where('school_name', 'like', '%' . $search . '%')
->orWhere('head_teacher', 'like', '%' . $search . '%')
->orWhereHas(['teachers'=>function($query) use ($search)
return $query->where('teacher_name', 'like', '%' . $search . '%');
]
)->get();
【讨论】:
以上是关于Laravel 通过属性获得雄辩的查询构建器关系的主要内容,如果未能解决你的问题,请参考以下文章