2013-06-06 3 views
0

영역과 작업의 관계가 many-to-many 인 ORM 요청을 필터링하고 싶습니다.Laravel 4 - 필터가있는 페이지 매기기 Eloquent ORM

페이지 매김이 필요하지만 $ final-> paginate()를 사용할 수는 없지만 그 이유는 무엇입니까? 사용하는

내 코드를, 개선 방법 -> PAGINATE() 더 Paginatore는 ::

/* sélectionne tout les candidats qui sont disponnibles, et qui ont une date inférieure 
    * à celle configuré 
    */ 
    $contacts = Candidate::with('regions', 'jobs') 
          ->where('imavailable', '1') 
          ->where('dateDisponible', '<=', $inputs['availableDate']) 
          ->get(); // ta requete pour avoir tes contacts, ou par exemple tu fais un tri normal sur tes regions. Il te reste à trier tes jobs. 

    // ajoute un filtre, pour n'afficher que ceux qui reponde true aux 2 test dans les foreachs 
    $final = $contacts->filter(function($contact) use($inputs) { 

     // par défaut ils sont false 
     $isJob = false; 
     $isRegion = false; 

     // test que le candidat à l'un des jobs recherché par l'entreprise 
     foreach($contact->jobs as $job) { 

      // si le job id du candidat est dans la liste, alors on retourne true 
      if(in_array($job->id, $inputs['job'])) { 

       $isJob = true; 
      } 
     } 
     // test que le candidat accepte de travailler dans l'une des régions echerchées 
     foreach($contact->regions as $region) { 

      // si region id du candidat est dans la liste, alors on retourne true 
      if(in_array($region->id, $inputs['region'])) { 

       $isRegion = true; 
      } 
     } 

     // si les 2 renvoie true, alors nous returnons le candidat à la vue 
     if($isRegion && $isJob){ 

      return true; 
     } 
     else{ 

      return false; 
     } 
    }); 

    // converti le resultat en tableau pour l'importer dans le Paginator 
    $finalArray = $final->toArray(); 

    // calcule le nombre de candidat dans le tableau 
    $finalCount = count($finalArray); 

    // créer le pagniate manuellement, car on ne peux faire $final->paginate(20) 
    $paginator = Paginator::make($finalArray, $finalCount, 2); 

    // return la liste des candidats 
    return $paginator; 

감사하지 않습니다.

답변

1

좋아는, 세 번째는 매력 ture, 쿼리가 아닙니다. 적절한 인덱스

ALTER TABLE `candidate_region` ADD INDEX `REGION_ID` ( `region_id`) 
ALTER TABLE `candidate_region` ADD INDEX `CANDIDATE_ID` ( `candidate_id`) 
ALTER TABLE `candidate_job` ADD INDEX `JOB_ID` ( `job_id`) 
ALTER TABLE `candidate_job` ADD INDEX `CANDIDATE_ID` ( `candidate_id`) 

피벗 테이블이 더 잘 작동 :

당신은 심각한 성능 향상을 얻을 수있는 다음과 같은 인덱스를 추가해야합니다. 이 쿼리는 두 번째에서 실행 위의 인덱스와

SELECT * 
FROM candidates 
INNER JOIN candidate_region 
ON candidates.id = candidate_region.candidate_id 
INNER JOIN candidate_job 
ON candidates.id = candidate_job.candidate_id 
WHERE imavailable = 1 AND dateDisponible <= '2013-12-31' AND region_id IN (2,3,4,43,42) AND job_id IN (1,2,5,8) 

: 두 번째

, 이것은 실행하려는 (순수) SQL 쿼리입니다. 인덱스가 없으면 내 컴퓨터에서 시간이 초과되었습니다. 셋째

이이 쿼리 유창함처럼 보일 것입니다 무엇 :

DB::table('candidates') 
    ->join('candidate_region', 'candidates.id', '=', 'candidate_region.candidate_id'); 
    ->join('candidate_job', 'candidates.id', '=', 'candidate_job.candidate_id'); 
    ->whereIn('candidate_region.region_id',$inputs['region']) 
    ->whereIn('candidate_job.job_id',$inputs['job']) 
    ->where('imavailable', '1') 
    ->where('dateDisponible', '<=', $inputs['availableDate']) 
    ->get(); // Or paginate() 

이 안된이지만, 그대로 또는 약간의 수정 작업을해야한다.

즐기십시오! 내가 2 피벗 사용하기 때문에

+0

감사합니다. 아주,하지만 어떻게 laravel 마이그레이션으로 'ADD INDEX'를 추가 할 수 있습니까? – timothylhuillier

+0

'$ table-> index ('state'); ' http://laravel.com/docs/schema#adding-indexes –

+0

oups, 나는 그것을 보지 못했습니다. 감사합니다 – timothylhuillier

0

필터()를 두 개의 단순한 간단한 whereIn()으로 바꾸지 않는 이유는 무엇입니까?

그런 식으로 원하는대로 페이지 매김()을 사용할 수 있어야합니다.

+0

는 : 지역 및 채용을 "candidate_region : 아이디, candidate_id, REGION_ID는" 및 "candidate_job : 아이디, candidate_id, 작업 ID" – timothylhuillier

+0

그것은 '당신이 할 수있는 것 eager-loaded 관계로 where()를 사용한다. [source를 보라] (http : // stackoverflow.com/questions/14621943/laravel-how-to-use-where-relationships-for-relations-column) 그러나 동일한 링크는 열심히로드하지 않고도 어떻게 수행 할 수 있는지 보여줍니다.)) 및 public 메소드를 사용하여 해당 피벗 테이블을 join()합니다. 지역 및 작업을 해당 메소드의 매개 변수로 전달하고 두 개의 내부 조인을 수행하면 필터링 된 데이터로 끝나야합니다. –

+0

나는 미안하다. ORM에 2 개의 조인()을 포함해야합니까? – timothylhuillier

0

이것은 어둠 속에서 촬영 한 것입니다. (저는 여기에 라우라벨 설정이 없습니다)하지만 그대로있는 것이 좋습니다.

은 가입하고 필터링을 수행하는 새로운 방법, 추가 할 후보 모델을 변경

: 당신이 원하는

class Candidate extends Eloquent { 

    /* Le code existant de ton modèle "Candidate" est ici */ 


    /* Nouvelle méthode qu'on ajoute au modèle pour le filtrer par region et job */ 

    public static function forRegionsAndJobs($regions, $jobs) 
    { 
     return static::join(
     'candidate_region', 
     'candidates.id', '=', 'candidate_region.candidate_id' 
    )->whereIn('region_id', $regions) 
     ->join(
     'candidate_job', 
     'candidates.id', '=', 'candidate_job.candidate_id' 
    )->where('job_id', $jobs); 
    } 
} 

는 그런 다음 필터를 그 모델을 호출하고 방법을 페이지를 매기 수 그것을 :

$contacts = Candidate::forRegionsAndJobs($inputs['region'], $inputs['job']) 
          ->where('imavailable', '1') 
          ->where('dateDisponible', '<=', $inputs['availableDate']) 
          ->paginate(25); 

먼저, 당신의 성능 문제는 데이터베이스 struc에서 온다 :

+0

고마워, 아주 좋은데 재발행에는 13/20 초가 걸리지 않는다. 피벗 작업과 지역이 없다. – timothylhuillier

+0

-> (...)를 다시 추가하여 관계를 얻을 수는 있지만 더 많은 시간을 질의를하고 DB에서 두 번 읽는다. 그래서 필자는 Fluent 또는 pure SQL에서이 쿼리를 작성하는 것이 모델과 Eloquent를 좋아하지 않는 이유는 훨씬 쉽고 빠르기 때문입니다. –

+0

고마워, 나는 Fluent request를하려고 노력 중이다. 그것은 작동하지 않거나 요청은 13 초 걸립니다. DB :: table ('candidate') -> ('candidate', function ($ join) {$ join-> on ('candidates.id', $ input [ 'region']) -> join ('regions', function ($ join) { $) ('candidate_job.job_id', $ inputs [ 'job']) -> 여기서 '('regions.id ','= ','candidate_region.region_id '); } - imavailable ','1 ') -> get();' – timothylhuillier