Reputation: 11
I'm using the Criteria elements for the first time, but I think it is simple enough I shouldn't be having any problem. Of course, a problem has appeared.
I have a OneToMany relation defined like this:
/**
* @ORM\OneToMany(targetEntity="ExpedientesMensajes", mappedBy="expediente", cascade={"remove"})
* @ORM\JoinColumn(name="id", referencedColumnName="id_expediente")
*/
private $mensajes;
Each of those has another relation, this:
/**
* @ORM\OneToMany(targetEntity="ExpedientesMensajesLeidos", mappedBy="mensaje")
* @ORM\JoinColumn(name="id", referencedColumnName="id_mensaje")
*/
private $mensajesLeidos;
Now, in the entity with the first relation, I have this method:
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;
}
It iterates over all the elements of the first relation, and uses the defined criteria on each of them, getting a subset of the collection of the elements from the second relation.
When the first relation $mensajes is just one element it works. But, when that collection is greater than that, for example three elements, the matching() method returns an empty array even when I'm seeing on the database that there are elements that match the requirements.
I've been able to get it to work doing
$mensaje->getMensajesLeidos()[0];
right before the matching() method, but AFAIK, I think that throws away the whole benefit of using the Criteria elements, because it initializes the collection. I've seen it working too when debugging and asking the debugger about that first element, which does the same as the instruction.
Does anybody have an idea of what is happening here?
Thanks in advance.
Upvotes: 1
Views: 1416
Reputation: 527
I rewritten your code in order to do not use several times the same Criteria. Maybe the problem comes from the reuse of it but not sure.
$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);
Upvotes: 1