2014-03-26 22 views
5

假設我有一個實體Profile,它與Account實體有關聯。我想獲取profileCode = 12345的配置文件,其相關的Account的電子郵件地址爲[email protected]。所以,我需要在兩個實體上指定一個條件。過濾與原則2中的標準對象關聯

爲此,我創建了一個自定義存儲庫Repository\Profile,現在我想知道如何實現這一點。我知道我可以用「原始」DQL查詢或使用查詢生成器來解決所有這些問題。不過,我覺得它並不像我想的那麼漂亮,因爲它非常接近原始SQL。當然,語法有點不同,但從概念上來說,我認爲SQL比OOP更多。我會做很多這樣的事情,所以我真的想以最好的方式做到這一點。

我已經在Criteria對象上進行了一些閱讀(文檔很稀疏),只要我在單個實體上過濾,它確實看起來很棒。在關聯實體上過濾時,我找不到任何解決方案使用Criteria

所以基本上我的問題是:有什麼方法可以使用Criteria對象直接從數據庫和自定義存儲庫中過濾多個實體?我會真的更喜歡在自定義存儲庫內編碼而不是實體本身,因爲我見過一些人。這是可能的,還是有其他更好的選擇,或者是簡單的DQL還是查詢構建器真的要走的路?

回答

1

條件只能篩選實體本身的關聯,但如果我理解了你的用例,則需要深入篩選2個級別,所以它不起作用。

您正試圖將教義塑造成不是的東西,因爲它想要「按照您的方式」做事。從長遠來看,它只會傷害你。解決方案已經存在,使用DQL是完全正確的,特別是在存儲庫中。

+0

我不會深入兩層。我想通過直接關聯的屬性進行過濾。例如,'A'與'B'關聯。我想找到'A'的條目,其中'B.something ='some_value''。如果可能,我只想確保在數據庫中完成工作。另外,我並不是試圖將教義塑造成不是的東西;我只是想知道是否有一種方法可以實現這種「我的方式」,這種方式是內置於教義中的,我不知道。否則,我將使用DQL就好了,但如果可能的話,我寧願使用'Criteria'對象。 :-) – Andy0708

+0

您無法使用Criterias搜索相關實體的屬性。您只能搜索實體本身的屬性。 –

+0

好的,那就是我的想法 - 不幸的是。謝謝。 – Andy0708

0

我不明白爲什麼不,但不知道你的關聯是如何相關的。 One-to-OneOne-to-Many,或Many-to-Many

如果你正在嘗試從第三關聯深度級別記錄,如Account.profile - >Profile.code - >Code.xxx (not id)你就需要使用DQL或或QueryBuilder的,以確定哪些個人資料和代碼分別爲加入賬戶或解決代碼實體提供給標準。

假設One-to-Many其中一個帳戶有許多配置文件。您也可以選擇在實體內定義它,以便管理和減少對getProfiles()的額外呼叫。

庫使用

use Doctrine\ORM\EntityRepository; 
use Doctrine\Common\Collections\Criteria; 

class AccountRepository extends EntityRepository { 

    /** 
    * @var string|Account $accountOrEmail 
    * @var string $code 
    * @return Profile|null 
    */ 
    public function getAccountProfileByEmailAndCode($accountOrEmail, $code) 
    { 
     try{ 
      $account = ($accountOrEmail instanceof Account ? $accountOrEmail: $this->findOneBy(['email' => $accountOrEmail])); 
      if (!$account instanceof Account) { 
       throw new \InvalidArgumentException('Unknown Account Specified.'); 
      } 
      $criteria = Criteria::create()->setMaxResult(1); 
      $expr = $criteria::expr(); 
      $criteria->where($expr->eq('code', $code)); 

      return $account->getProfiles()->matching($criteria)->first(); 
     } catch(\Exception $e) { 
      return null; 
     } 
    } 

} 
$accountRepo = $em->getRepository('\Entities\Account'); 
$profile = $accountRepo->getAccountProfileByEmailAndCode('[email protected]', '12345'); 

實體使用

use Doctrine\Common\Collections\Criteria; 

/** 
* @ORM\Entity(repositoryClass="AccountRepository") 
*/ 
class Account { 

    // ... 

    public function getProfiles(Criteria $criteria = null) 
    { 
     if ($criteria instanceof Criteria) { 
      return $this->profiles->matching($criteria); 
     } 

     return $this->profiles; 
    } 

    /** 
    * @var string $code 
    * @return null|Profile 
    */ 
    public function getProfileByCode($code) 
    { 
     $criteria = Criteria::create()->setMaxResult(1); 
     $expr = $criteria::expr(); 
     $criteria->where($expr->eq('code', $code)); 

     return $this->getProfiles($criteria)->first(); 
    } 

} 
$account = $em->getRepository('\Entities\Account')->findOneBy(['email' => '[email protected]']); 
$profile = $account->getProfileByCode('12345');