2015-11-02 92 views
3

我必須簡單的實體:日誌和用戶。 日誌與Entity具有ManyToOne關係。如何使用inner join時優化多個Doctrine查詢?

Log: 
    type: entity 
    repositoryClass: LogRepository 
    id: 
    id: 
     type: integer 
     generator: 
     strategy: AUTO 
    fields: 
    message: 
     type: string  
    manyToOne: 
    user: 
     targetEntity: User 
     joinColumns: 
     user_id: 
      referencedColumnName: id 

我用例是顯示日誌列表和一個或兩個有關用戶(如他的名字和他的例如電子郵件)

如果我使用findall方法,Symfony的調試工具欄告訴我,學說執行了很多查詢。一個查詢爲我提供日誌,併爲每個用戶執行一個查詢!這當然不好,因爲我認爲我可以有一千個日誌。我不想超載我的數據庫服務器。這個問題似乎很容易解決。但我正在尋找一段時間,結果似乎是「不好的做法」。

於是,我開始使用的QueryBuilder在LogRepository類寫一個新的方法:

public function getLog(){ 
     $qb = $this->createQueryBuilder('l') 
      ->select('l') 
      ->innerJoin(
       'ApplicationSonataUserBundle:User', 'u', 
       Expr\Join::WITH,'l.user = u.id') 
     ; 
     return $qb->getQuery()->getResult(); 
} 

我仍然有同樣的問題。我已經將我的方法上的選擇參數更改爲:

public function getLog(){ 
     $qb = $this->createQueryBuilder('l') 
      ->select('l','u') 
      ->innerJoin('ApplicationSonataUserBundle:User','u', 
         Expr\Join::WITH,'l.user = u.id') 
     ; 
     return $qb->getQuery()->getResult(); 
} 

Eureka?好的,我只有一個查詢,但我的方法並沒有只返回日誌,但用戶太...所以我的樹枝模板崩潰,因爲我的循環包含用戶,而不僅僅是日誌。當這是一個用戶時,我的視圖崩潰,因爲我想寫消息字段。 (Log.message的存在,但User.message不是有效的領域,當然)。

它的工作原理相當不錯,如果我改變一次我的方法有循環過濾我的結果:

public function getLog(){ 
     $qb = $this->createQueryBuilder('l') 
      ->select('l','u') 
      ->innerJoin('ApplicationSonataUserBundle:User','u', 
         Expr\Join::WITH,'l.user = u.id') 
     ; 
     //THE STRANGE LOOP 
     $results = array(); 
     foreach ($qb->getQuery()->getResult() as $result){ 
      if ($result instanceof Log){ 
       $results[] = $result; 
      } 
     }; 
     return $results; 
} 

我只有一個查詢,這是我正在尋找的。我的樹枝模板不會崩潰,因爲我的數組只包含Log。

那麼,有什麼事?它有效,但我認爲這不是好的/最佳實踐。

有人可以解釋我一個更好的辦法,更好的做法是使用內部聯接查詢,最大限度地減少執行查詢,並有一個包含日誌的唯一實例的ArrayCollection結果?

回答

3

它不應該有必要使用循環。試試這樣:

public function getLog(){ 
    $qb = $this->createQueryBuilder('l') 
     ->select('l','u') 
     ->innerJoin('l.user', 'u'); 
    $logs = $qb->getQuery()->getResult(); 
    return $logs; 
} 

它應該只用填充(讀取加盟)協會用戶返回$logs

+0

和 - 如果你知道如何使用它,要小心:如果你真的只需要用戶的一個或兩個屬性(和用戶,否則是一個非常大的對象),你可以使用部分語法只需要取用戶的屬性。 – LBA

+0

非常感謝!即使工作完成,我也知道我做錯了。作爲我的使用案例,學說似乎很簡單。而我的代碼似乎太複雜。謝謝。這十分完美 ! @LBA:謝謝我會看看部分語法。用戶可以是一個大對象,我只需要他的名字和他的郵件。頭像,blob信息不必檢索。感謝您的信息! –