Doctrine 2: Construir una consulta dinámica iterando sobre una matriz de parámetros (condiciones AND)
Estoy tratando de averiguar cómo iterar correctamente en un array en una consulta personalizada del repositorio de Symfony 5.
Me explico. El usuario de la aplicación puede revisar varios valores en una página. Quiero mostrar objetos que coincidan con todos (pero no necesariamente solo) los valores marcados.
Fácilmente atrapo una matriz de los valores que envío a un controlador con Ajax, pero encuentro problemas con mi consulta personalizada.
Los valores coinciden con el parámetro “label” de una tabla (Tag) que está relacionada (ManyToMany) con la tabla (Flash) que selecciono con mi consulta.
Hasta ahora, he intentado muchas cosas, como:
public function getFlashesByTagsList($tags)
{
$qb = $this->createQueryBuilder('f');
$andX = $qb->expr()->andX();
$qb->join('f.tags', 't');
$qb->addSelect('t');
foreach ($tags as $tag) {
$andX->add(
$qb->expr()->like('t.label', ':tag'),
$qb->setParameter(':tag', '%' . $tag . '%')
);
}
$qb->add('where', $andX);
$qb->orderBy('f.id', 'DESC');
$result = $qb->getQuery()->getResult();
return $result;
}
Pero nada de lo que intenté funcionó. Si solo se envía un valor, obtengo todos los objetos que tienen este valor en sus etiquetas, pero tan pronto como hay más, solo obtengo los que coinciden con el último en el array $tags.
davy.ai
Para iterar correctamente en un arreglo dentro de una consulta personalizada de un repositorio en Symfony 5, se puede usar el bucle
foreach
con una expresiónandX
para crear una consulta que coincida con todos los valores seleccionados.En tu código de ejemplo, estás uniendo la tabla
tags
con la tablaFlash
y seleccionando la tablatags
. Luego, estás iterando a través del arreglo de valores seleccionados y agregando una expresiónlike
a la expresiónandX
para cada uno.Sin embargo, estás sobrescribiendo el parámetro
:tag
para cada iteración del bucle, por lo que solo se está utilizando el último valor seleccionado. Para solucionar esto, se puede usar un nombre de parámetro único para cada iteración, como:tag1
,:tag2
, etc.Aquí está una versión actualizada de tu código que debería funcionar:
Esto debería devolver objetos que coincidan con todos los valores seleccionados, en lugar del último.