2016-10-01 73 views
2

我有一个User模型,其中包含属性type以及其他属性。类型用于识别父母儿童Laravel:基于雄辩关系获取用户

父母和子女(学生)有多对多的关系。 同时学生属于一个或多个(模型Group)。

用户模型

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

上述关系是否正常工作。

下面是我的关联表。

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 |  | 
+------------+------------------+------+-----+ 

我需要找到不属于任何群组的学生以及他们的父母。我设法找到学生像这样

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

问: 现在我想找到这些学生的家长。但我无法为此建立一个雄辩的查询。我该怎么做?

注:我可以从上面的查询让学生收集和运行foreach循环才能得到父母的,像这样

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

但我需要一个Builder对象,而不是Collection因为我使用Datatables server side processingYajra/datatables

+0

使用User :: student() - > with('parents')。这是关系的急切加载https://laravel.com/docs/5.3/eloquent-relationships#eager-loading – Silwerclaw

+0

但这不会直接给我父母。他们将在嵌套关系中。我更喜欢为父母获得一个'Builder'对象。 – linuxartisan

+0

ok - 然后你可以加载你的学生,然后调用$ students-> load(['parents' - > function($ query){//根据需要修改你的构建器}]) – Silwerclaw

回答

0

嗯,我设法解决它像这样

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

我仍然会喜欢它,如果有人能提出一个更好的和简单的方法。

2

对于加载parents关系你hae使用急切加载。 2种方法是with($relation)load($relation)。区别仅仅是让父母已经有了结果对象,或者以后再加载它们。

在你的榜样

因此要得到父母可以用(“父母”)使用或如果要修改结果集:

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

然后你会得到你父母的关系藏汉,但性能将因为您只会花费一次查询将父母加载到对象中。然后,如果需要,他们在一个收集这样你就可以采摘:

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

或示例2 - 如果你只需要与选择的学生家长们 - 几乎是相同的东西预先加载的功能:

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

修订

为了得到父母的建设者试试这个:

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

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

这将为您创建BelongsToMany关系的新实例,并将whereIn($ studentIds)的约束附加到它。然后打->get()上它,你必须接受相关的$父母

+0

我仍然不明白我将如何为父母获取“生成器”对象。 – linuxartisan

+0

你需要'Builder'对象来做什么?根据您的示例,您希望“在查询级别处理这个速度会更快。” - 我已经为您提供了一种方法来为父母加载一个查询 – Silwerclaw

+0

对不起。我正在使用数据表服务器端处理。我更新了我的问题。 – linuxartisan