Php 如何在Doctrine和ORM之间进行查询

Php 如何在Doctrine和ORM之间进行查询,php,doctrine-orm,zend-framework2,Php,Doctrine Orm,Zend Framework2,使用Docrtine 2和Zend Framework 2,我有一个如下工作的服务: class TransactionService { public function __construct(TransactionMapperInterface $transactionMapper) { $this->transactionMapper = $transactionMapper; } public function findBy($c

使用Docrtine 2和Zend Framework 2,我有一个如下工作的服务:

class TransactionService 
{
    public function __construct(TransactionMapperInterface $transactionMapper)
    {
        $this->transactionMapper = $transactionMapper;
    }

    public function findBy($conditions = array(), $order = array(), $limit = null, $offset = null)
    {
        return $this->transactionMapper->findBy($conditions, $order, $limit, $offset);
    }
}
但我需要查询中间条件,如以下结果:

select * from transactions where created between '2014-02-01' and '2014-03-01';

这在findBy方法中是可能的?

简言之,否。
findBy
仅用于简单查询,而您的
之间的
不属于这一部分

然而,它可以做得相对简单:我会使用
Doctrine\ORM\Query\Filter\SQLFilter
来做这种查询,这是since中的一个新特性

其工作方式是创建一个从基
SQLFilter
类扩展而来的类,并向其添加您自己的过滤器约束。启用过滤器时,之后基于该特定实体的任何查询都将应用此过滤器

对于您的特定问题,可以执行以下操作(假设
事务
表实际上是一个名为
ORM\entity\transactions
的实体)

<?php

namespace ORM\Filter;

use Doctrine\ORM\Mapping\ClassMetaData;
use Doctrine\ORM\Query\Filter\SQLFilter;

/**
 * This filter filters on records between two given dates.
 */
class BetweenFilter extends SQLFilter
{
    public function addFilterConstraint(ClassMetaData $targetEntity, $targetTableAlias)
    {
        // First check if the entity implements the BeteenAware interface
        if (!$targetEntity->reflClass->implementsInterface('ORM\Filter\BetweenAware')) {
            return "";
        }

        // We know now that our table supports the between entity, please note
        // that getParameter automatically quotes variables
        return sprintf(
            '(created BETWEEN %s AND %s)',
            $this->getParameter('betweenFrom'),
            $this->getParameter('betweenTo')
        );
    }
}
此时剩下的就是添加过滤器、设置参数并启用过滤

// We'll ASSUME that the $config variable is a valid Doctrine configuration object retrieved 
// by instances such as `Setup::createAnnotationMetadataConfiguration`. On the other hand
// the variable $connection is assumed to contain valid connection details.

// First add the filter to the configuration
$config->addFilter('between', 'ORM\Filter\BetweenFilter');

// Now create the EntityManager
$entityManager = EntityManager::create($connection, $config);

// We will now enable our filter and set the parameters
$entityManager
->getFilters()
->enable('between')
->setParameter('betweenFrom', '2014-02-01')
->setParameter('betweenTo', '2014-03-01')
;

// Now for the moment supreme, lets get all the records back
$records = $entityManager
->getRepository('ORM\Entity\Transactions')
->findAll()
;
我还没有测试过代码,所以我不确定它是否没有错误,但这绝对是一种很好的过滤记录的方法,不会造成混乱

希望这能回答你的问题。我不介意投票,但请让我知道为什么,这样我们都可以学习


不要忘记将
ORM\Filter\BetweenAware
接口添加到实体类中,否则该过滤器将被忽略。

简言之,否。
findBy
仅用于简单查询,而您的
BetweenAware
不是其中的一部分

然而,它可以做得相对简单:我会使用
Doctrine\ORM\Query\Filter\SQLFilter
来做这种查询,这是since中的一个新特性

其工作方式是创建一个从基本
SQLFilter
类扩展而来的类,并向其添加您自己的筛选约束。启用筛选后,基于该特定实体的任何查询都将应用此筛选

对于您的特定问题,可以执行以下操作(假设
事务
表实际上是一个名为
ORM\entity\transactions
的实体)

<?php

namespace ORM\Filter;

use Doctrine\ORM\Mapping\ClassMetaData;
use Doctrine\ORM\Query\Filter\SQLFilter;

/**
 * This filter filters on records between two given dates.
 */
class BetweenFilter extends SQLFilter
{
    public function addFilterConstraint(ClassMetaData $targetEntity, $targetTableAlias)
    {
        // First check if the entity implements the BeteenAware interface
        if (!$targetEntity->reflClass->implementsInterface('ORM\Filter\BetweenAware')) {
            return "";
        }

        // We know now that our table supports the between entity, please note
        // that getParameter automatically quotes variables
        return sprintf(
            '(created BETWEEN %s AND %s)',
            $this->getParameter('betweenFrom'),
            $this->getParameter('betweenTo')
        );
    }
}
此时剩下的就是添加过滤器、设置参数并启用过滤

// We'll ASSUME that the $config variable is a valid Doctrine configuration object retrieved 
// by instances such as `Setup::createAnnotationMetadataConfiguration`. On the other hand
// the variable $connection is assumed to contain valid connection details.

// First add the filter to the configuration
$config->addFilter('between', 'ORM\Filter\BetweenFilter');

// Now create the EntityManager
$entityManager = EntityManager::create($connection, $config);

// We will now enable our filter and set the parameters
$entityManager
->getFilters()
->enable('between')
->setParameter('betweenFrom', '2014-02-01')
->setParameter('betweenTo', '2014-03-01')
;

// Now for the moment supreme, lets get all the records back
$records = $entityManager
->getRepository('ORM\Entity\Transactions')
->findAll()
;
我还没有测试过代码,所以我不确定它是否没有错误,但这绝对是一种很好的过滤记录的方法,不会造成混乱

希望这能回答你的问题。我不介意投票,但请让我知道为什么,这样我们都可以学习


不要忘记将
ORM\Filter\BetweenAware
接口添加到实体类,否则过滤器将被忽略。

我找到了另一种更简单的方法。 好的,使用
findBy
这是不可能的,但我们可以使用
createQueryBuilder
,请参见一个小示例:

$qb = $this->transactionMapper->createQueryBuilder('transaction');

$query = $qb->select('t')
            ->from('Transaction\Entity\Transaction', 't')
            ->where($qb->expr()->between('t.created', "'2014-02-01'", "'2014-03-01'"));

return $query->getQuery()->getResult();

参见文档

我找到了另一种更简单的方法。 好的,使用
findBy
这是不可能的,但我们可以使用
createQueryBuilder
,请参见一个小示例:

$qb = $this->transactionMapper->createQueryBuilder('transaction');

$query = $qb->select('t')
            ->from('Transaction\Entity\Transaction', 't')
            ->where($qb->expr()->between('t.created', "'2014-02-01'", "'2014-03-01'"));

return $query->getQuery()->getResult();

请参阅文档

抱歉,我找到了一个更简单的方法。谢谢帮助。抱歉,我找到了一个更简单的方法。谢谢帮助。