在原则 2 中选择日期之间的条目
Posted
技术标签:
【中文标题】在原则 2 中选择日期之间的条目【英文标题】:Select entries between dates in doctrine 2 【发布时间】:2012-07-18 04:27:21 【问题描述】:我会因为这个我没有得到修复的最小错误而发疯。我想在两天之间选择条目,下面的例子说明了我所有的失败:
选择 1。
$qb->where('e.fecha > ' . $monday->format('Y-m-d'));
$qb->andWhere('e.fecha < ' . $sunday->format('Y-m-d'));
结果(0 个条目):
SELECT r0_.id_reservacion AS id_reservacion0, r0_.fecha AS fecha1, r0_.cliente AS cliente2
FROM reservacion r0_
WHERE (r0_.fecha > 2012 - 07 - 16) AND (r0_.fecha < 2012 - 07 - 22)
选择 2
$qb->add('where', 'e.fecha between 2012-01-01 and 2012-10-10');
结果(0 个条目):
SELECT r0_.id_reservacion AS id_reservacion0, r0_.fecha AS fecha1, r0_.cliente AS cliente2
FROM reservacion r0_ WHERE r0_.fecha
BETWEEN 2012 - 01 - 01 AND 2012 - 10 - 10
这是我的当前条目表:
id fecha cliente
1 2012-07-16 00:00:00 2
2 2012-07-16 13:00:00 4
3 2012-07-22 23:00:00 4
编辑 1
为了评估 sql 以避免疑虑,我运行了这个查询:
$qb->where('e.fecha > ' . $sunday->format('Y-m-d'));
结果(3 个条目):
SELECT r0_.id_reservacion AS id_reservacion0, r0_.fecha AS fecha1, r0_.cliente AS cliente2
所以,看起来 sql 不是问题。 FROM 预订 r0_ WHERE r0_.fecha > 2012 - 07
【问题讨论】:
只是一个问题,直到专家来 - 您需要制作这些日期字符串吗?我的意思是,例如,第一个生成的 WHERE 有r0_.fecha > 2012 - 07 -16
- 它不应该看起来更像 r0_.fecha > '2012-07-16'
或类似的吗?
完全同意你的看法。但请查看更新后的帖子
嗯,好吧——当你引用时会发生什么?
好吧,在我疯狂的时刻,我肯定犯了一个错误或错字。引用日期不会影响查询:D(正如我一开始所想的那样)。
【参考方案1】:
编辑:查看其他答案以获得更好的解决方案
我提供的原始新手方法是(opt1):
$qb->where("e.fecha > '" . $monday->format('Y-m-d') . "'");
$qb->andWhere("e.fecha < '" . $sunday->format('Y-m-d') . "'");
和(opt2):
$qb->add('where', "e.fecha between '2012-01-01' and '2012-10-10'");
这既快速又简单,并且可以立即制作原始海报。
因此接受的答案。
根据 cmets,这是错误的答案,但很容易犯错误,所以我把它留在这里作为“不该做什么!”
【讨论】:
我选择了您的第二个选项并且效果很好,这个愚蠢的查询花了我整个下午的时间哇。很好,非常感谢! 这实际上是一种非常错误的做法,您永远不应该将变量直接连接到查询中 - 您应该真正使用参数:docs.doctrine-project.org/projects/doctrine-dbal/en/latest/… 虽然它确实有效,但这是错误的,甚至是危险的,最好完全删除答案......【参考方案2】:你可以选择……
$qb->where('e.fecha BETWEEN :monday AND :sunday')
->setParameter('monday', $monday->format('Y-m-d'))
->setParameter('sunday', $sunday->format('Y-m-d'));
或者……
$qb->where('e.fecha > :monday')
->andWhere('e.fecha < :sunday')
->setParameter('monday', $monday->format('Y-m-d'))
->setParameter('sunday', $sunday->format('Y-m-d'));
【讨论】:
+2 用于参数。不使用参数是非常危险的,否则 Doctrine 无法正确转义它们 这可能会破坏与某些数据库平台的兼容性,例如 Microsoft SQL Server,其中没有 Date 类型并且所有内容都以“Y-m-d H:i:s.000”的形式保存。您应该让 Doctrine 通过将类型定义为setParameter()
的第三个参数来处理转换,例如 setParameter('monday', $monday, \Doctrine\DBAL\Types\Type::DATE)
。
模拟BETWEEN
的比较运算符是>=
和<=
,而不是>
和<
。
你也可以使用:->where($qb->exp()->between('e.fecha', ':monday', ':sunday')
@MatíasNavarroCarter : ->where($qb->expr()->between('e.fecha', ':monday', ':sunday')
你错过了expr()
中的r
【参考方案3】:
我相信正确的做法是使用查询构建器表达式:
$now = new DateTimeImmutable();
$thirtyDaysAgo = $now->sub(new \DateInterval("P30D"));
$qb->select('e')
->from('Entity','e')
->add('where', $qb->expr()->between(
'e.datefield',
':from',
':to'
)
)
->setParameters(array('from' => $thirtyDaysAgo, 'to' => $now));
http://docs.doctrine-project.org/en/latest/reference/query-builder.html#the-expr-class
编辑:与此处的任何其他答案相比,此方法的优势在于它独立于数据库软件 - 您应该让 Doctrine 处理日期类型,因为它具有处理此类事情的抽象层。
例如,如果您以 'Y-m-d' 形式添加字符串变量,当它转到 mysql 以外的数据库平台时,它将中断。
【讨论】:
非常感谢您的回答...这是日期比较的唯一方法....其他答案中给出的所有方法都不适合我:) 谢谢 - 这确实是在 Doctrine 中进行日期比较的唯一真正独立于平台的方式。 我同意,但不应该是->setParameters(array(':from' => $thirtyDaysAgo, ...
吗?
@AndreschSerj:实际上不应该。见doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/…。【参考方案4】:
看看我如何在参数中格式化我的日期 $jour。 这取决于你使用 expr()->like 还是 expr()->lte
$qb
->select('e')
->from('LdbPlanningBundle:EventEntity', 'e')
->where(
$qb->expr()->andX(
$qb->expr()->orX(
$qb->expr()->like('e.start', ':jour1'),
$qb->expr()->like('e.end', ':jour1'),
$qb->expr()->andX(
$qb->expr()->lte('e.start', ':jour2'),
$qb->expr()->gte('e.end', ':jour2')
)
),
$qb->expr()->eq('e.user', ':user')
)
)
->andWhere('e.user = :user ')
->setParameter('user', $user)
->setParameter('jour1', '%'.$jour->format('Y-m-d').'%')
->setParameter('jour2', $jour->format('Y-m-d'))
->getQuery()
->getArrayResult()
;
【讨论】:
以上是关于在原则 2 中选择日期之间的条目的主要内容,如果未能解决你的问题,请参考以下文章