2013-08-09 1 views
8

the Doctrine Docs에 따라 기준을 설정하려고합니다.교리 2.3 기준. 관련 개체 액세스

불행히도 관련 객체의 속성에 액세스하는 방법을 알려주지 않습니다. 내가 한 가지 예를 들어 보겠다.

제품 ArrayCollection을 보유하고 있습니다. 모든 제품에는 카테고리가 있습니다. 카테고리 이름에 대한 ArrayCollection을 필터링하고 싶습니다. 지금은 다음과 같은 기준을 설정하려고 :

$criteria = Criteria::create() 
    ->where(Criteria::expr()->eq("category.name", "SomeCategoryName")); 

지금은 다음과 같은 예외가 얻을 : 나는 관련 개체에 액세스 할 수있는 방법

An exception has been thrown during the rendering of a template ("Unrecognized field: category.name") 

를?

답변

5

소스 코드 Criteria::expr()->eq("name", --- second value ---)을 조사했습니다. 두 번째 값은 Doctrine\Common\Collections\Expr\Value의 인스턴스를 나타냅니다. 따라서 Expr 또는 criteria을 입력 할 수 없습니다. ExprAndOr 만 다른 Expr이됩니다. filter()과 같은 다른 함수를 사용하여이 문제를 해결하거나 getIterator()을 사용하여 반복기를 생성한다고 가정합니다. 이것이 filter() 메소드로 수행되는 방법입니다.

$filteredProducts = 
    $products->filter(function($key, $element) use ($categoryName) { 
     return $element->getCategory()->getName() === categoryName; 
    }); 

만약 당신이 할 수있는 당신이 그 안에 둥지 foreach는 루프와 필터를 할 수있는 다음의 각 관계에 대한 Iterator.

+1

답장을 보내 주셔서 감사합니다. 나는 월요일에 당신의'Ctriteria'을 테스트 할 것입니다. 지금은 워크 스테이션에 액세스 할 수 없습니다. 작동하는지 알려 드리겠습니다. 그러나 필자의 의견으로는 필터가 좋지 않습니다. 왜냐하면 모든 범주가로드되고 디스크에서 로컬로 처리되기 때문입니다 (DB에서 수행하는 것보다 성능이 떨어지는 것은 아닐 수 있습니다). – Robin

+0

당신이 잘못 알고 있습니다. 조건은 쿼리 (가져올 데이터)와 ArrayCollection (이미 가져온 데이터)에서 사용할 수 있습니다. fetch-join을 만들지 않았다면 criteria 나 filter()를 사용하든 상관없이 관계가 열심히로드 될 것입니다. 당신은 DB가 당신에게 최고의 성능을 제공 할 수 있도록 WHERE와 함께 fetch join을 사용하는 것이 가장 좋습니다. 그것이 당신의 질문이 아니었지만. – Flip

+0

엔티티에 주석을 달아 게으른로드가 가능할 것이라고 생각했습니다. http : // docs.doctrine-project.org/en/2.0.x/reference/annotations-reference.html#annref-manytoone. 'ArrayCollection'을 느슨하게로드하지 않겠습니까? 또는 이것이 반대 주석이므로 작동하지 않겠습니까? – Robin

2

아마도 필터 방법이 아닌 저장소 방법에 속할 것입니다. 부모 객체 (예 : Order 또는 무언가)의 컬렉션에 사전 필터링 된 제품 목록을 가져 오려면 쿼리 작성기에서 하위 컬렉션을 필터링 할 수 있습니다. 그러나, 당신은 충분히 수화 된 물체를 가지지 않는 것의 혼란스러운 부작용을 다루어야합니다.

Product 개의 하위 카테고리 이름과 일치하는 Order 개의 개체 목록을 제공해야합니다.

class OrderRepository extends EntityRepository { 
    public function findOrderWithProductCategory($category) 
    { 
    $builder = $this->createQueryBuilder('o') 
     ->select('o, p') 
     ->leftJoin('o.products', 'p') 
     ->join('p.category', 'c', 'WITH', 'c.name = :category') 
     ->setParameter('category', $category); 
    } 
} 

당신이 그때는 아마 더 나은 어쨌든 @ 플립의 솔루션을 사용하고있는 모든 범주를 미리 수화하고, 나중에까지 관심 카테고리의 종류를 모르는 경우

. partial hydration과 표준 ArrayCollection::filter() 클로저를 사용하면 대부분의 경우 거의 잘 수행됩니다.

그건 그렇고, 그것은 기능으로 아주 좋을 것이라고 말했습니다. 나는 현재의 Criteria 구현이 매우 가볍기 때문에 교리 녀석들이 꺼릴 것이라고 생각한다.

+0

실제로 [문제] (https://github.com/doctrine/collections/pull/27)가 이미 열렸습니다. – yvoyer