2016-10-01 79 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