2016-10-01 3 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 processing с Yajra/datatables ,

+0

использование Пользователь :: student() -> with ('parents'). Это страстная загрузка отношений https://laravel.com/docs/5.3/eloquent-relationships#eager-loading – Silwerclaw

+0

Но это не даст мне родителей напрямую. Они будут внутри вложенных отношений. Я предпочел бы получить объект «Builder» для родителей. – linuxartisan

+0

ok - тогда вы можете загрузить своих учеников и после этого вызова $ students-> load (['parent' -> 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(); 

Тогда вы получите ваши родитель в отношениях Aswell, но производительность будет что вы будете тратить только один запрос на загрузку родительских объектов. Тогда вы можете срывать при необходимости их в одну коллекцию, как это:

$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 и добавит Constraints of whereIn ($ studentIds) к нему.Тогда ударять ->get() на него, вы должны получить связанные с $ родителей

+0

Я до сих пор не понимаю, как я получу объект «Builder» для родителей. – linuxartisan

+0

вам нужен объект 'Builder' для чего? Согласно вашему примеру, вы хотите: «Обработка этого на уровне запросов будет намного быстрее». - Я предоставил вам способ загрузить родителей одним запросом – Silwerclaw

+0

Извините за это. Я использую обработку серверных данных datatables. Я обновил свой вопрос. – linuxartisan

Смежные вопросы