Cách sử dụng phương pháp findBy với các tiêu chí so sánh


75

Tôi cần sử dụng phương pháp findB "công cụ tìm ma thuật" bằng cách sử dụng tiêu chí so sánh (không chỉ tiêu chí chính xác). Nói cách khác, tôi cần làm điều gì đó như sau:

$result = $purchases_repository->findBy(array("prize" => ">200"));

để tôi nhận được tất cả các giao dịch mua mà giải thưởng trên 200.


6
Nếu bạn nghĩ rằng học thuyết hoặc symfony không phải là thứ của bạn, bạn vừa chọn sai một khuôn khổ cho dự án của mình. Các khuôn khổ này hoạt động hiệu quả cho nhiều dự án.
mask 8

1
tại sao nó có để được như vậy khó hiểu
javier_domenech

Câu trả lời:


30

Đây là một ví dụ sử dụng Lớp Expr () - Tôi cũng cần điều này vài ngày trước và tôi đã mất một thời gian để tìm ra cú pháp chính xác và cách sử dụng:

/**
 * fetches Products that are more expansive than the given price
 * 
 * @param int $price
 * @return array
 */
public function findProductsExpensiveThan($price)
{
  $em = $this->getEntityManager();
  $qb = $em->createQueryBuilder();

  $q  = $qb->select(array('p'))
           ->from('YourProductBundle:Product', 'p')
           ->where(
             $qb->expr()->gt('p.price', $price)
           )
           ->orderBy('p.price', 'DESC')
           ->getQuery();

  return $q->getResult();
}

13
Tránh sử dụng DQL nếu không thực sự cần thiết, nó chỉ làm cho logic của bạn ngày càng được kết hợp nhiều hơn với ORM.
Ocramius

9
@Sliq đây là một hành vi học thuyết và không nhất thiết phải liên quan đến symfony.
con

12
@Sliq sau khi bạn thử một số khuôn khổ hơn, bạn sẽ nhận ra rằng Symfony không phải là quá crappy
Marián Zeke Šedaj

Nếu tôi thấy chính xác, chức năng này là một phương pháp kho lưu trữ. Tại đây, bạn có thể đi thẳng đến $this->createQueryBuilder('p')thay vì đi vòng quanh, thông qua EntityManager : $this->getEntityManager()->createQueryBuilder().
Ngây ngô

201

Lớp Doctrine\ORM\EntityRepositorytriển khai Doctrine\Common\Collections\SelectableAPI.

Các Selectablegiao diện là rất linh hoạt và khá mới, nhưng nó sẽ cho phép bạn xử lý so sánh và tiêu chí phức tạp hơn một cách dễ dàng trên cả hai kho và bộ sưu tập duy nhất của mặt hàng, không phân biệt nếu trong ORM hay ODM hoặc các vấn đề hoàn toàn riêng biệt.

Đây sẽ là một tiêu chí so sánh như bạn vừa yêu cầu như trong Doctrine ORM 2.3.2:

$criteria = new \Doctrine\Common\Collections\Criteria();
$criteria->where($criteria->expr()->gt('prize', 200));

$result = $entityRepository->matching($criteria);

Ưu điểm chính trong API này là bạn đang triển khai một số loại mô hình chiến lược ở đây và nó hoạt động với các kho lưu trữ, bộ sưu tập, bộ sưu tập lười biếng và ở mọi nơi mà SelectableAPI được triển khai.

Điều này cho phép bạn loại bỏ hàng tá phương pháp đặc biệt mà bạn đã viết cho kho lưu trữ của mình (như findOneBySomethingWithParticularRule) và thay vào đó tập trung vào việc viết các lớp tiêu chí của riêng bạn, mỗi lớp đại diện cho một trong những bộ lọc cụ thể này.


2
Lưu ý: Tôi đang sử dụng symfony 2.8.11 với học thuyết và - có thể chỉ ở đó - đó là "Criteria :: expr () -> gt ()", không phải "$ tiêu chí-> expr () -> gt ()".
Chọn 0r

3
Đó là một phương thức tĩnh: github.com/doctrine/collections/blob/… Ngoài ra: Symfony KHÔNG phải là Doctrine. Học thuyết tham khảo công cụ với tên học thuyết và versioning :-P
Ocramius

@Ocramius thì $criteria::expr()->gt()lý tưởng nhất là nó phải không?
Adrian Föder

2
Criteria::expr()cũng được - vui lòng chỉnh sửa câu trả lời.
Ocramius

1
Có các phương pháp lưu trữ cụ thể như findOneBySomethingWithParticularRuleIMO là một điều tốt vì nó tách rời logic nghiệp vụ của bạn khỏi các chi tiết triển khai Doctrine như trình tạo tiêu chí.
David

6

Bạn phải sử dụng DQL hoặc QueryBuilder . Ví dụ: trong Purchase- EntityRepository của bạn, bạn có thể làm điều gì đó như sau:

$q = $this->createQueryBuilder('p')
          ->where('p.prize > :purchasePrize')
          ->setParameter('purchasePrize', 200)
          ->getQuery();

$q->getResult();

Đối với các trường hợp phức tạp hơn, hãy xem lớp Expr () .


5
Tránh sử dụng DQL ở những nơi không cần thiết. Nó khóa bạn vào API cụ thể của ORM và không thực sự có thể sử dụng lại được. Có một số trường hợp yêu cầu DQL, nhưng đây không phải là một trong những trường hợp đó.
Ocramius

6
làm thế nào để việc sử dụng QueryBuilder không khóa bạn vào học thuyết theo cùng một cách?
NDM



0

Tôi thích sử dụng các phương thức tĩnh như vậy:

$result = $purchases_repository->matching(
    Criteria::create()->where(
        Criteria::expr()->gt('prize', 200)
    )
);

Tất nhiên, bạn có thể đẩy logic khi nó là 1 điều kiện, nhưng khi bạn có nhiều điều kiện hơn thì tốt hơn nên chia nó thành các đoạn, cấu hình và chuyển nó cho phương thức:

$expr = Criteria::expr();

$criteria = Criteria::create();
$criteria->where($expr->gt('prize', 200));
$criteria->orderBy(['prize' => Criteria::DESC]);

$result = $purchases_repository->matching($criteria);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.