简体   繁体   English

Laravel 按属性获取雄辩的查询构建器关系

[英]Laravel get eloquent query builder relations by property

I am using the eloquent query builder to build a search query conditionally depending on the parameters provided by the users search query.我正在使用 eloquent 查询构建器根据用户搜索查询提供的参数有条件地构建搜索查询。

This seems to work for attributes that directly belong to the model i am searching for.这似乎适用于直接属于我正在搜索的模型的属性。 However, i'm having issues when trying to return additional results that are related to the model but don't directly belong to the model.但是,在尝试返回与模型相关但不直接属于模型的其他结果时,我遇到了问题。

What i am trying to do exactly:我正在尝试做的正是:

I'm trying to allow users to search schools by teacher name where the name/keyword appears in a relation of the school through an intermediary table.我试图允许用户按教师姓名搜索学校,其中姓名/关键字通过中间表出现在学校的关系中。

Here are my models and relationships:这是我的模型和关系:

School:学校:

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

Teacher:老师:

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

I can successfuly query the teachers through a school in a controller using $school->teachers so i know the relationship is working fine.我可以使用$school->teachers teachers 通过控制器中的学校成功查询$school->teachers因此我知道这种关系运行良好。

Here is my code for the controller where the users search parameters are conditionally built up:这是我的控制器代码,其中有条件地建立用户搜索参数:

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

        })

} }

The two initial where clauses return the correct results when searching by a school name or head_teacher as these two properties directly belong to a school.当按学校名称或 head_teacher 搜索时,两个初始 where 子句返回正确的结果,因为这两个属性直接属于一个学校。 However, i'd like to return additional schools that include a teachers name through the relationship.但是,我想通过这种关系返回包含教师姓名的其他学校。

So a school can belong to many teachers and vice versa through the intermediary teacher_link table but i don't know how to accurately filter this this using the eloquent query builder.因此,一所学校可以通过中间的 Teacher_link 表属于许多教师,反之亦然,但我不知道如何使用 eloquent 查询构建器准确地过滤这一点。

Initially i tried using the union function and joins which worked but broke subsequent where clauses as it doesn't seem to allow where clauses to follow after union queries.最初,我尝试使用 union 函数和 joins 工作,但破坏了后续的 where 子句,因为它似乎不允许在 union 查询之后跟随 where 子句。

It would be great if someone could tell me what i'm doing wrong and how i can fix the query in question:如果有人能告诉我我做错了什么以及我如何解决有问题的查询,那就太好了:

            // This is the query i'm having an issue with
            ->whereHas('teachers', function($q) use ($search) {
                $q->where('teacher_name', 'like', '%' . $search . '%');
            });

EDIT编辑

I have tried the following which seems to work but it is slow:我尝试了以下似乎有效但速度很慢的方法:

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

Try using orWhereHas in that query instead.尝试在该查询中使用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 . '%');
        });
    });

Try using eloquent relationship尝试使用雄辩的关系

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM