2016-03-05 82 views
0

一個user和他coupons,我希望得到一個用戶和他所有的優惠券:學說2,避免讓給未連接的實體

foreach ($this->createQueryBuilder('x')->select('u, c')->where('x.email = ?0')->setParameter(0, $email)->leftJoin('u.coupons', 'c')->getQuery()->getResult() as $entity) 
{ 
    $entity->getCoupons(); 
} 

這是非常好的,直到我忘記加入優惠券:

foreach ($this->createQueryBuilder('x')->select('u')->where('x.email = ?0')->setParameter(0, $email)->getQuery()->getResult() as $entity) 
{ 
    $entity->getCoupons(); 
} 

不幸的是,即使沒有加入優惠券,這仍然有效。在這裏它執行另一個SELECT。另外,這第二選擇將是錯誤的。 Id寧可想要得到一個異常,或者至少需要一個空數組。有沒有解決方法?

回答

2

你正在經歷的是預期的教義行爲。

當您選擇User實體時,Doctrine將從數據庫中獲取記錄。如果您沒有明確加入Coupon實體(或與User有關係的任何其他實體),Doctrine將創建一個Proxy對象。一旦你通過調用$user->getCoupons()來訪問這個代理對象,Doctrine會向數據庫發出一個新的查詢來獲得你的User實體的優惠券。這被稱爲lazy-loading

我不確定是否有辦法按照您所描述的方式更改此設置。

你可以做的是在你的UserRepository中創建一個名爲findUserAndCoupons($email)的方法,並在那裏查詢。每當你需要找到一個用戶,他的優惠券,你可以簡單地使用檢索它在你的控制器:

class MyController extends Controller { 
    public function myAction(){ 
     $user = $this->getDoctrine()->getRepository('UserRepository')->findUserAndCoupons($email); 

     foreach($user->getCoupons() as $coupon) { 
      // .... 
     } 
    } 

} 

這樣你就不需要記住實際的查詢和複製/粘貼所有的地方。 :)