【问题标题】:Doctrine Criteria not working unless collection is initialized除非初始化集合,否则 Doctrine Criteria 不起作用
【发布时间】:2020-04-27 22:37:52
【问题描述】:

我是第一次使用 Criteria 元素,但我认为它足够简单,我应该不会有任何问题。当然,问题出现了。

我有一个这样定义的 OneToMany 关系:

/**
 * @ORM\OneToMany(targetEntity="ExpedientesMensajes", mappedBy="expediente", cascade={"remove"})
 * @ORM\JoinColumn(name="id", referencedColumnName="id_expediente")
 */
private $mensajes;

每个都有另一个关系,这个:

/**
 * @ORM\OneToMany(targetEntity="ExpedientesMensajesLeidos", mappedBy="mensaje")
 * @ORM\JoinColumn(name="id", referencedColumnName="id_mensaje")
 */
private $mensajesLeidos;

现在,在第一个关系的实体中,我有这个方法:

function isLeidoPor($idControlAcceso = null)
{
    // http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html#filtering-collections
    $criteria = Criteria::create()
        ->where(Criteria::expr()->eq('idControlAcceso', $idControlAcceso))
        ->setMaxResults(1);

    // El expediente es leído si hay mensajes...
    if (0 < count($this->getMensajes())) {
        // y todos han sido leidos por el control de acceso que pasamos.
        // (No se puede usar un Criteria para campos en los campos de los miembros de la colección.)
        foreach ($this->getMensajes() as $mensaje) {
            $mensaje->getMensajesLeidos()[0];
            if (0 == count($mensaje->getMensajesLeidos()->matching($criteria))) {
                return false;
            }
        }

        return true;
    }

它遍历第一个关系的所有元素,并对每个元素使用定义的标准,从第二个关系中获取元素集合的子集。

当第一个关系 $mensajes 只是一个元素时,它可以工作。但是,当该集合大于该集合时,例如三个元素,ma​​tching() 方法会返回一个空数组,即使我在数据库中看到有符合要求的元素也是如此。

我已经能够让它工作了

$mensaje->getMensajesLeidos()[0];

就在 ma​​tching() 方法之前,但是 AFAIK,我认为这会抛弃使用 Criteria 元素的全部好处,因为它会初始化集合。我在调试并向调试器询问第一个元素时也看到了它的工作原理,它与指令的作用相同。

有人知道这里发生了什么吗?

提前致谢。

【问题讨论】:

  • 当我点击您在 cmets 中提供的链接时,我可以在文档中看到:"[...] If the collection has not been loaded from the database yet [...]"。也许您似乎无法循环使用条件,它解释了为什么当您只有一个条目时它会起作用。

标签: symfony doctrine-orm criteria


【解决方案1】:

我重写了您的代码,以免多次使用相同的标准。也许问题来自于它的重用但不确定。

$criteria = Criteria::create()
->where(Criteria::expr()->eq('idControlAcceso', $idControlAcceso))
->setMaxResults(1);

// We get an array with number of leidos for each mensaje
$mappedOccurrencies = $this
    ->getMensajes()
    ->map(function(ExpedientesMensajes $mensaje) use ($criteria) {
        $mensaje
            ->getMensajesLeidos()
            ->matching($criteria)
            ->count();
    });
// Then if we have at least a mensaje with 0 leidos, we return false (true otherwise)
return !in_array(0, $mappedOccurrencies);

【讨论】:

  • 请考虑添加至少一些文字向 OP 解释,并让更多读者回答为什么以及如何回答原始问题。
  • Pierre-Chanel 这对返回值很有用,但我看不出它会以何种方式帮助解决主要问题。
猜你喜欢
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-01
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
相关资源
最近更新 更多