2013-08-09 53 views
8

Tôi đang cố gắng thiết lập Tiêu chí theo the Doctrine Docs.Học thuyết 2.3 Tiêu chí. Truy cập một đối tượng liên quan

Rất tiếc, họ không cho bạn biết cách truy cập các thuộc tính của đối tượng liên quan. Tôi sẽ cho bạn một ví dụ.

Tôi có một ArrayCollection of Products. Mỗi Sản phẩm đều có Danh mục. Tôi muốn lọc ArrayCollection cho một Category Name. Bây giờ tôi đang cố gắng để thiết lập một tiêu chuẩn như sau:

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

Bây giờ tôi nhận được ngoại lệ sau:

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

Làm thế nào tôi có thể truy cập vào một đối tượng có liên quan?

Trả lời

5

Tôi đã xem mã nguồn Criteria::expr()->eq("name", --- second value ---). Giá trị thứ hai mong đợi một phiên bản của Doctrine\Common\Collections\Expr\Value. Vì vậy, không thể đặt một số khác là Expr hoặc criteria trong đó. Chỉ ExprAndOr lấy một số Expr khác. Tôi chắc chắn bạn giả sử để giải quyết vấn đề này với các chức năng khác như filter() hoặc nhận một trình lặp với getIterator(). Đây là cách nó có thể được thực hiện với phương pháp filter().

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

Nếu bạn có thể Iterator cho mỗi mối quan hệ tiếp theo, bạn có thể lồng vòng foreach và lọc bên trong.

+1

Cảm ơn câu trả lời của bạn. Tôi sẽ kiểm tra 'Ctriteria' của bạn vào thứ hai. Ngay bây giờ tôi không có quyền truy cập vào máy trạm của tôi. Tôi sẽ cho bạn biết nếu nó hoạt động. Tuy nhiên bộ lọc là một ý tưởng tồi trong quan điểm của tôi, bởi vì tất cả các hạng mục sẽ được háo hức nạp và sau đó xử lý cục bộ trên đĩa (Những gì sẽ không bao giờ được như perfomant hơn làm nó trên một DB). – Robin

+0

Bạn bị hiểu sai. Tiêu chí có thể được sử dụng trong một truy vấn (dữ liệu được lấy) cũng như trên một ArrayCollection (đã được lấy dữ liệu). Nếu bạn không thực hiện tìm nạp-tham gia thì mối quan hệ sẽ được tải sẵn nếu bạn sử dụng tiêu chí hoặc bộ lọc(). Bạn nói đúng là DB cung cấp cho bạn hiệu suất cao nhất, vì vậy tốt nhất bạn nên sử dụng tìm nạp kết hợp với WHERE. Mặc dù đó không phải là câu hỏi của bạn. – Flip

+0

Tôi nghĩ rằng nó sẽ có thể chú thích các thực thể của bạn, để họ được lười biếng nạp? http: // tài liệu.doctrine-project.org/en/2.0.x/reference/annotations-reference.html#annref-manytoone. Sẽ không tải lười biếng 'ArrayCollection'? Hay điều đó không có tác dụng vì đó là chú thích nghịch đảo? – Robin

2

Điều đó có thể thuộc về một phương pháp lưu trữ, chứ không phải là phương pháp lọc. Nếu bạn muốn nhận danh sách Sản phẩm được lọc trước trong bộ sưu tập trên đối tượng cha mẹ (như Đơn hàng hoặc thứ gì đó), bạn có thể lọc bộ sưu tập con trong trình tạo truy vấn. Tuy nhiên, bạn phải đối phó với tác dụng phụ có thể gây nhầm lẫn của việc không có các đối tượng hoàn toàn ngậm nước.

Điều này sẽ cung cấp cho bạn danh sách các đối tượng Order, chỉ có Product trẻ em phù hợp với tên danh mục.

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); 
    } 
} 

Nếu bạn không biết những gì loại danh mục mà bạn quan tâm đến sau này, sau đó bạn có lẽ tốt hơn sử dụng giải pháp @ Flip dù sao, và tiền hydrating tất cả các loại. Sử dụng partial hydration và tiêu chuẩn ArrayCollection::filter() đóng cửa, hoạt động khá tốt trong hầu hết các trường hợp.

Điều đó nói rằng, nó sẽ khá đẹp như một tính năng. Tôi nghi ngờ các học viên Doctrine sẽ miễn cưỡng vì hiện tại thực hiện Criteria là rất nhẹ và họ có thể muốn giữ nó theo cách đó.

+0

thực sự, [vấn đề] này (https://github.com/doctrine/collections/pull/27) đã được mở: – yvoyer