Doctrine在可空日期类型上忽略IS NULL / IS NOT NULL

时间:2018-03-14 18:55:44

标签: php mysql symfony doctrine-orm repository

我注意到Symfony应用程序上有一个奇怪的行为。

我们有一个包含可以为空的日期字段的实体:

/**
 * @var \DateTime
 *
 * @ORM\Column(name="foo", type="date", nullable=true)
 */
private $foo;

只获取设置条目的相应查询如下所示:

public function findFoo()
{
    $qb = $this->_em->createQueryBuilder();
    $qb
        ->select('e')
        ->from($this->_entityName, 'e')
        ->where('e.foo IS NOT NULL');

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

然而,此查询将返回所有条目,甚至是那些在db中设置为Null的条目。

转储foo字段的值时,我们得到:

object(DateTime)[549]
  public 'date' => string '-0001-11-30 00:00:00.000000' (length=27)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)

我们尝试修改查询以使用此where子句:

->where($qb->expr()->isNotNull('e.foo'))

但结果仍然相同。我们现在已经解决了这个“黑客”:

->where('e.foo > :dateSet')
->setParameter('dateSet', new \DateTime('1970-01-01'))

诀窍是什么,但有点不合适。

问题:在可以为空的日期字段中检查Doctrine查询中IS NOT NULL的正确方法是什么?这是教条或预期行为中的错误吗?如果是预料到的,那是什么原因呢?

编辑: 后续问题,我们如何测试IS NULL?在这种情况下,->where('e.foo IS NULL');->where('e.foo < :dateSet');->where('e.foo <= :dateSet');接缝都不起作用。注意:我还尝试使用dateSet的当前日期。当然,我现在可以使用NOT IN( ... )并在那里查询非空的查询,但这将更加黑客。现在我可能不得不决定PHP方面。

编辑:根据要求,该类的相关部分包括构造函数

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * FooBar
 *
 * @ORM\Table(name="foo_bar")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\FooBarRepository")
 */
class FooBar
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // [...]

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="foo", type="date", nullable=true)
     */
    private $foo;

    public function __construct()
    {
        $this->foo = null;
        // [...]
    }

    // [...]

    public function isFoo(): bool
    {
        return !is_null($this->foo);
    }

    // [...]

    /**
     * Set foo
     *
     * @param \DateTime $foo
     *
     * @return FooBar
     */
    public function setFoo($foo)
    {
        $this->foo = $foo;

        return $this;
    }

    /**
     * Get foo
     *
     * @return \DateTime|null
     */
    public function getFoo()
    {
        return $this->foo;
    }
}

1 个答案:

答案 0 :(得分:1)

所以最后的问题是,有问题的字段曾经是一个不可空的布尔值,我把它变成了一个可以为空的日期。我认为所有的值都应该为null,实际上在使用SQL工具进行检查时,它会将所有值都显示为null。

然而在内部它接缝它们毕竟不是空的。我运行update foo_bar set foo = NULL;来修复我的所有问题。

我不确定它是否是教条本身的错误,我认为这是MySQL方面的一个问题。