简体   繁体   English

Laravel:根据 Eloquent 关系获取用户

[英]Laravel: Get users based on Eloquent relation

I have a User model which has an attribute type among other attributes.我有一个User模型,它在其他属性中具有一个属性type Type is used to identify parents and children .类型用于识别父母孩子

Parent and children (students) have many-to-many relationship.父母和孩子(学生)是多对多的关系。 Also students belong to one or many groups (model Group ).学生也属于一个或多个(模型Group )。

User model用户模型

/**
 * Filter the scope of users to student type.
 *
 * @param $query
 */
public function scopeStudent($query){
    $query->where('type', '=', 'std');
}

/**
 * Filter the scope of users to parent type.
 *
 * @param $query
 */
public function scopeParent($query){
    $query->where('type', '=', 'prt');
}

/**
 * List of groups the user is associated with.
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function groups(){
    return $this->belongsToMany('\App\Group', 'group_user_assoc')
                ->withTimestamps();
}

/**
 * List of students associated with the user(parent).
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function children(){
    return $this->belongsToMany('\App\User', 'student_parent_assoc', 'parent_id', 'student_id')
                ->withPivot('relation');
}

/**
 * List of parents associated with the user(student).
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function parents(){
    return $this->BelongsToMany('\App\User', 'student_parent_assoc', 'student_id', 'parent_id')
                ->withPivot('relation');
}

The aforementioned relations are working correctly.上述关系工作正常。

Below are my association tables.下面是我的关联表。

student_parent_assoc
----------------------
+------------+------------------+------+-----+
| Field      | Type             | Null | Key |
+------------+------------------+------+-----+
| student_id | int(10) unsigned | NO   | PRI |
| parent_id  | int(10) unsigned | NO   | PRI |
| relation   | varchar(25)      | YES  |     |
+------------+------------------+------+-----+

group_user_assoc
----------------------
+------------+------------------+------+-----+
| Field      | Type             | Null | Key |
+------------+------------------+------+-----+
| group_id   | int(10) unsigned | NO   | MUL |
| user_id    | int(10) unsigned | NO   | MUL |
| created_at | timestamp        | NO   |     |
| updated_at | timestamp        | NO   |     |
+------------+------------------+------+-----+

I need to find students who do not belong to any group along with their parents.我需要找到不属于任何团体的学生和他们的父母。 I have managed to find students like so我已经设法找到这样的学生

$students = User::student()
                ->whereDoesntHave('groups')
                ->get();

Question: Now I want to find parents of these students.问:现在我想找到这些学生的家长。 But I am not able to build an eloquent query for the same.但是我无法为其构建雄辩的查询。 How do I do it?我该怎么做?

Note: I could get collection of students from above query and run a foreach loop to get their parents like so注意:我可以从上面的查询中收集学生并运行foreach循环来让他们的父母像这样

$parents = new Collection;
foreach($students as $student) {
    foreach($student->parents as $parent) {
        $parents->push($parent);
    }
}
$parents = $parents->unique();

But I need a Builder object and not a Collection as I am using Datatables server side processing with Yajra/datatables .但是我需要一个Builder对象而不是一个Collection因为我使用的是Yajra/datatables 的Datatables 服务器端处理

for loading parents relation you hae to use eager loading.对于加载parents关系,您必须使用预先加载。 2 methods are with($relation) and load($relation) . 2 种方法是with($relation)load($relation) Difference is just you get parents already with result objects or load them later.不同之处在于您让父母已经拥有结果对象或稍后加载它们。

So in your example to get parents you can use with('parents') or if you want to modify resulted set:因此,在您获取父母的示例中,您可以使用 with('parents') 或者如果您想修改结果集:

User::student()
->with(['parents' => function ($parentsQueryBuilder) {
    $parentsQueryBuilder->where('condition', 1)->whereIn('condition2', [1,2,3]);
}])
->whereDoesntHave('groups')
->get();

Then you will get your parents in a relationship aswell but performance will be high cause you will spend only one query to load parents to your objects.然后你也会让你的父母建立关系,但性能会很高,因为你只需要一个查询来将父母加载到你的对象中。 Then you can pluck if needed them in one collection like this:然后,您可以根据需要将它们收集到一个集合中,如下所示:

$students->pluck('parents')->flatten()->unique();

Or example 2 - if you just need all parents related to selected students - almost the same what eager loading does:或示例 2 - 如果您只需要与选定学生相关的所有家长 - 与预先加载几乎相同:

$studentIds = $students->modeKeys();
User::parent()->whereHas('children', function ($query) use($studentIds) {
    $query->whereIn('id', $studentIds);
})->get();

UPDATED更新

For getting builder of parents try this:为了让父母的建设者试试这个:

/** BelongsToMany   <- relation query builder */    
$relation = with(new User)->query()->getRelation('parents');

$relation->addEagerConstraints($students->all());

This will create for you new instance of BelongsToMany relation and attach Constraints of whereIn($studentIds) to it.这将为您创建 BelongsToMany 关系的新实例并将 whereIn($studentIds) 的约束附加到它。 Then hitting ->get() on it you have to receive related $parents然后点击->get()你必须收到相关的 $parents

Well, I managed to solve it like so好吧,我设法解决了它

$students = User::student()
                ->with('parents')
                ->whereDoesntHave('groups')
                ->has('parents') //to get only those students having parents
                ->get();

$parent_ids = array();

// get ids of all parents
foreach ($students as $student) {
    foreach ($student->parents as $parent) {
        $parent_ids[] = $parent->user_id;
    }
}

// build the query
$users = User::parent()
             ->with('children')
             ->whereIn('user_id', $parent_ids);

I would still like it if someone could suggest a better and simple approach.如果有人可以提出更好和更简单的方法,我仍然会喜欢它。

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

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