除非集合被初始化,否则学说标准无法工作。

问题描述 投票:1回答:1

我是第一次使用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 是只有一个元素,它可以工作。但是,当该集合大于该元素时,例如三个元素,则 匹配() 方法返回一个空数组,即使我在数据库中看到有符合要求的元素。

我已经能够让它工作,做了

$mensaje->getMensajesLeidos()[0];

前面 匹配() 方法,但AFAIK,我认为这样做会丢掉使用Criteria元素的全部好处,因为它初始化了集合。我看到它在调试时也在工作,并向调试器询问第一个元素,它的作用与指令相同。

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

先谢谢你了。

symfony doctrine-orm criteria
1个回答
1
投票

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

$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);
© www.soinside.com 2019 - 2024. All rights reserved.