2015-09-11 6 views
0

Я пытался решить эту проблему в течение 3 дней, но не нашел решения.Laravel - как использовать whereHas с условными отношениями?

У меня есть условное отношение один-к-одному между таблицей пользователей и их профили admin_profile, teacher_profile, student_profile и company_pofile

отношения в пользовательской модели выглядит следующим образом:

function profile() { 
    switch ($this -> type) { 
     case 'other': 
      return $this -> hasOne('App\AdminProfile'); 
     break; 
     case 'company': 
      return $this -> hasOne('App\CompanyProfile'); 
     break; 
     case 'teacher': 
      return $this -> hasOne('App\TeacherProfile'); 
     break; 
     case 'student': 
      return $this -> hasOne('App\StudentProfile'); 
     break; 
    } 
} 

И как это условно, нетерпевая загрузка не будет работать до того, как я назову метод «получить» или один из его братьев и сестер. так что я использовал «нагрузку», чтобы получить профиль пользователя так:

function getUser($id) { 
    $user = User::find($id) -> load('profile'); 

    return response() -> json($user); 
} 

Теперь проблема заключается в том, что я хочу, чтобы искать пользователей по данным в их профилях, так что я сделал это:

if($request -> has('filter')) { 
    $users -> whereHas('profile', function ($q) use($request) { 
     $filter = explode($request -> filter, ','); 
     $q -> where ($filter[0], @$filter[1]); 
    }); 
} 

и, конечно, из-за условной связи, жадная загрузка не будет работать, а вот сообщение об ошибке:

FatalErrorException в Builder.php линии 580: Вызов функции-члена getRelationCountQuery() на нуль

ответ

0

Я сам поехал по этому пути, и это было болезненно. Я бы настоятельно рекомендовал вам использовать Полиморфные отношения Ларавеля. Если вы не можете, лучший способ справиться с этим - это делать индивидуальные запросы для каждого типа отношений. Однако, чтобы быть в состоянии сделать это, вы должны разделить ваши отношения так:

public function adminProfile { 
    return $this->hasOne('App\AdminProfile'); 
} 

public function companyProfile { 
    return $this->hasOne('App\CompanyProfile'); 
} 

public function teacherProfile { 
    return $this->hasOne('App\TeacherProfile'); 
} 

public function studentProfile { 
    return $this->hasOne('App\StudentProfile'); 
} 

public function profile() { 
    switch ($this->type) { 
     case 'other': 
      return $this->adminProfile(); 
      break; 
     case 'company': 
      return $this->companyProfile(); 
      break; 
     case 'teacher': 
      return $this->teacherProfile(); 
      break; 
     case 'student': 
      return $this->studentProfile(); 
      break; 
     default: 
      throw new Exception('Unknown Type: '. $this->type); 
    } 
} 

И затем получить результаты, как так:

$students = User::where('type', 'student')->whereHas('studentProfile', function ($q) use($request) { 
    $filter = explode($request -> filter, ','); 
    $q -> where ($filter[0], @$filter[1]); 
}); 


$teachers = User::where('type', 'teacher')->whereHas('teacherProfile', function ($q) use($request) { 
    $filter = explode($request -> filter, ','); 
    $q -> where ($filter[0], @$filter[1]); 
}); 


$company = User::where('type', 'company')->whereHas('companyProfile', function ($q) use($request) { 
    $filter = explode($request -> filter, ','); 
    $q -> where ($filter[0], @$filter[1]); 
}); 

Однако, если вы можете использовать полиморфных Отношения, они созданы именно по этой причине и сделают вещи намного проще.

«Полиморфные отношения позволяют модели относиться к более чем одной другой модели в одной ассоциации». - Ларавел знает, как работают полиморфные отношения, и добавил поддержку всех красноречивых функций.

http://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations

+0

Спасибо за ваш ответ, я думаю, теперь я застрял, потому что я сделал много функциональных возможностей на основе «профиль». Однако я думал, что полиморфные отношения используются для отношений «один-много и много-много», верно? – Salahuddin

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