Laravel 通过 属性 获取 eloquent 查询构建器关系

Laravel get eloquent query builder relations by property

我正在使用 eloquent 查询构建器根据用户搜索查询提供的参数有条件地构建搜索查询。

这似乎适用于直接属于我正在搜索的模型的属性。但是,我在尝试 return 与模型相关但不直接属于模型的其他结果时遇到问题。

我到底想做什么:

我正在尝试允许用户通过中介 table.

按教师姓名搜索学校,其中 name/keyword 出现在学校的关系中

这是我的模型和关系:

学校:

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'
    ];

}

教师链接:

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 . '%');
                });

        })

}

两个首字母 where 子句 return 按学校名称或 head_teacher 搜索时的正确结果,因为这两个属性直接属于学校。但是,我想 return 其他学校通过关系包含教师姓名。

所以一所学校可以通过中间人 teacher_link table 属于许多教师,反之亦然,但我不知道如何使用 eloquent 查询生成器准确过滤这个.

最初我尝试使用 union 函数和连接,它起作用但破坏了后续的 where 子句,因为它似乎不允许在 union 查询后跟随 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 . '%');
        });

尝试在该查询中使用 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 . '%');
        });
    });

尝试使用 eloquent 关系

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