php 如何在学说 2 实体的存储库中使用复杂的标准?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5349790/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:06:43  来源:igfitidea点击:

How do I use a complex criteria inside a doctrine 2 entity's repository?

phpsqldoctrinecriteriadoctrine-orm

提问by Doron

Lets say I have a table that holds information about festivals.
Each festival has a start and end date.

假设我有一张表格,其中包含有关节日的信息。
每个节日都有开始和结束日期。

I want to select all the festivals that are live (that happen) on a given date.
Meaning, I want to select all the festivals that their start date is before or on a given date, and that their end date is after or on a the same given date.

我想选择在给定日期现场(发生)的所有节日。
意思是,我想选择开始日期早于或在给定日期,并且结束日期晚于或在同一给定日期的所有节日。

So I went on to the repository class of the festival entity, and created a method to do just that.
But the criteria argument "findBy" expects is an array, which all the examples only treat as a simple criteria (eg. "array('name' => 'billy')" will select all the rows that have the value billy in their name column), which uses only the comparison operator.

所以我继续使用节日实体的存储库类,并创建了一个方法来做到这一点。
但是标准参数“findBy”期望是一个数组,所有示例仅将其视为一个简单的标准(例如,“array('name' => 'billy')”将选择在其name 列),它仅使用比较运算符。

How can I use other operators such as

我如何使用其他运算符,例如

>, <, !=, IN, NOT IN, LIKE    

and etc. ?

等等。 ?

Thanks

谢谢

采纳答案by Jeremy Hicks

You'll need to write your own query (probably using DQL) if you want something that specific. I believe the built in "findBy" methods are more for just grabbing objects quickly if you have less specific criteria. I don't know your entity names or where they are stored. Could be something like this as a function in your Festival Repository.

如果您想要特定的内容,则需要编写自己的查询(可能使用 DQL)。我相信内置的“findBy”方法更适合用于快速抓取对象,如果您的标准不那么具体。我不知道您的实体名称或它们的存储位置。可能是这样的东西作为您的节日存储库中的功能。

public function findActiveFestivals($start, $end)
{
    $qb = $this->_em->createQueryBuilder();
    $qb->select('f')
        ->from('Festival', 'f')
        ->where('f.start >= :start')
        ->andWhere('f.end <= :end')
        ->setParameters(array('start' => $start, 'end' => $end));

    return $qb->getQuery()->getArrayResult();
}

回答by Reece45

Doctrine 2.3 added a matching()method that lets you use Criteria.

Doctrine 2.3 添加了一个matching()方法,让您可以使用Criteria

The example by Jeremy Hicks may be written like this (note, this returns an ArrayCollection instead of an array).

Jeremy Hicks 的例子可能是这样写的(注意,这将返回一个 ArrayCollection 而不是一个数组)。

public function findActiveFestivals($start, $end)
{
    $expr = Criteria::expr();
    $criteria = Criteria::create();
    $criteria->where($expr->gte('start', $start));
    $criteria->andWhere($expr->lte('end', $end);
    return $this->matching($criteria);
}

Personally, I wouldn't use andWhere here, and use a few more lines to improve readability, like this:

就个人而言,我不会在这里使用 andWhere,而是使用更多行来提高可读性,如下所示:

public function findActiveFestivals($start, $end)
{
    $expr = Criteria::expr();
    $criteria = Criteria::create();
    $criteria->where(
      $expr->andX(
        $expr->gte('start', $start),
        $expr->lte('end', $end)
      )
    );
    return $this->matching($criteria);
}

Using an IN clause is very simple.

使用 IN 子句非常简单。

public function findFestivalsByIds($ids)
{
    $expr = Criteria::expr();
    $criteria = Criteria::create();
    $criteria->where($expr->in('id', $ids));
    return $this->matching($criteria);
}

The Criteria class is in Doctrine's not-really-ORM-or-DBAL Common's namespace, like their ArrayCollection (which has supported Criteria longer than EntityRepository).

Criteria 类位于 Doctrine 的非 ORM 或 DBAL Common 的命名空间中,就像它们的 ArrayCollection(它支持 Criteria 的时间比 EntityRepository 长)。

Its meant to be a decoupled way for non-repository code to create sophicated criteria. So it should be fine to use this class outside of the repository. QueryBuilder supports Criteriarecently as well. So even when building more sophisticated queries that require QueryBuilder, you can use Criteria to give the non-database code flexibility in what it requests.

它旨在成为非存储库代码创建复杂标准的解耦方式。所以在存储库之外使用这个类应该没问题。QueryBuilder最近也支持 Criteria。因此,即使在构建需要 QueryBuilder 的更复杂的查询时,您也可以使用 Criteria 为非数据库代码提供其请求的灵活性。

回答by nuenuh

thats not the answer for Doron question doctrine have entity repository that not make us using query at all...

这不是 Doron 问题的答案 教义有实体存储库,根本不让我们使用查询......

$this->em->getRepository($this->entity)->findBy(array $criteria);

but what did he asked is how to complex operator in array $criteria normal format of array $criteriais array('field'=> $value);

但他问的是如何在数组 $criteria 正常格式的数组中复杂运算符$criteriaarray('field'=> $value);

回答by rikbruil

I have had the same problem a while back, where my Doctrine repositories became very ugly due to complex queries. I also had to convert Yii ActiveRecord (with Criteria objects) to Doctrine, and Doctrine did not have Criteria objects at the time.

不久前我遇到了同样的问题,由于复杂的查询,我的 Doctrine 存储库变得非常难看。我还必须将 Yii ActiveRecord(带有 Criteria 对象)转换为 Doctrine,而 Doctrine 当时没有 Criteria 对象。

I found a blogpost by Benjamin Eberleiwhich has an interesting solution to this problem based on the specification pattern.

我找到了Benjamin Eberlei 的一篇博文,它基于规范模式对这个问题有一个有趣的解决方案。

It gives you the ability to defer the manipulation of the Query Builder object to other classes.

它使您能够将 Query Builder 对象的操作推迟到其他类。

$spec = new AndX(
    new Equals('ended', 0),
    new OrX(
        new LowerThan('endDate', new \DateTime()),
        new AndX(
            new IsNull('endDate'),
            new LowerThan('startDate', new \DateTime('-4weeks'))
        )
    )
);

return $this->em->getRepository('Advertisement')->match($spec)->execute()

Furthermore you can compose 2 or more classes together, which creates nice reusable building blocks:

此外,您可以将 2 个或更多类组合在一起,这会创建很好的可重用构建块:

public function myQuery(User $user)
{
    $spec = new AndX(
        new ExpiredAds(),
        new AdsByUser($user)
    );

    return $this->em->getRepository('Advertisement')->match($spec)->execute();
}

In this case ExpiredAds() and AdsByUser() contain a structure like in the first code example.

在这种情况下, ExpiredAds() 和 AdsByUser() 包含与第一个代码示例中类似的结构。

If you think that solution would work for you, let me suggest two libraries which you can install through composer:

如果您认为该解决方案适合您,让我建议您可以通过 composer 安装两个库: