php - symfony2 - orm symfony 4
¿Cómo uso un criterio complejo dentro del repositorio de una entidad de doctrine 2? (4)
Tendrá que escribir su propia consulta (probablemente usando DQL) si quiere algo tan específico. Creo que los métodos integrados de "findBy" son más para simplemente agarrar objetos rápidamente si tienes criterios menos específicos. No sé los nombres de sus entidades ni dónde están almacenados. Podría ser algo así como una función en tu Repositorio de Festivales.
public function findActiveFestivals($start, $end)
{
$qb = $this->_em->createQueryBuilder();
$qb->select(''f'')
->from(''Festival'', ''f'')
->where(''f.start >= :start'')
->andWhere(''f.end <= :end'')
->setParameters(array(''start'' => $start, ''end'' => $end));
return $qb->getQuery()->getArrayResult();
}
Digamos que tengo una mesa que contiene información sobre festivales.
Cada festival tiene una fecha de inicio y finalización.
Quiero seleccionar todos los festivales que están en vivo (que suceden) en una fecha determinada.
Es decir, quiero seleccionar todos los festivales que su fecha de inicio sea anterior o en una fecha determinada, y que su fecha de finalización sea posterior o en la misma fecha dada.
Así que fui a la clase de repositorio de la entidad del festival y creé un método para hacerlo.
Pero el argumento de criterios "findBy" espera que sea una matriz, que todos los ejemplos solo tratan como un criterio simple (por ejemplo, "array (''name'' => ''billy'')" seleccionará todas las filas que tengan el valor billy en su nombre de la columna), que usa solo el operador de comparación.
¿Cómo puedo usar otros operadores como
>, <, !=, IN, NOT IN, LIKE
y etc. ?
Gracias
esa no es la respuesta para la doctrina de la pregunta de Doron tener un repositorio de entidad que no nos haga usar la consulta en absoluto ...
$this->em->getRepository($this->entity)->findBy(array $criteria);
pero ¿qué es lo que preguntó es cómo compleja operador en matriz $ criterios formato normal de matriz $criteria
es array(''field''=> $value);
Hace un tiempo tuve el mismo problema, cuando mis repositorios de Doctrine se volvieron muy feos debido a consultas complejas. También tuve que convertir Yii ActiveRecord (con objetos Criteria) a Doctrine, y Doctrine no tenía objetos Criteria en ese momento.
Encontré un blogpost de Benjamin Eberlei que tiene una solución interesante a este problema basada en el patrón de especificación .
Le da la capacidad de diferir la manipulación del objeto Query Builder a otras clases.
$spec = new AndX(
new Equals(''ended'', 0),
new OrX(
new LowerThan(''endDate'', new /DateTime()),
new AndX(
new IsNull(''endDate''),
new LowerThan(''startDate'', new /DateTime(''-4weeks''))
)
)
);
return $this->em->getRepository(''Advertisement'')->match($spec)->execute()
Además, puede componer 2 o más clases juntas, lo que crea agradables bloques de construcción reutilizables:
public function myQuery(User $user)
{
$spec = new AndX(
new ExpiredAds(),
new AdsByUser($user)
);
return $this->em->getRepository(''Advertisement'')->match($spec)->execute();
}
En este caso, ExpiredAds () y AdsByUser () contienen una estructura como en el primer ejemplo de código.
Si crees que la solución funcionaría para ti, déjame sugerirte dos bibliotecas que puedes instalar a través del compositor:
- Happyr / Doctrine-Specification
- RikBruil / Doctrine-Specification (descargo de responsabilidad: soy el autor de este)
Doctrine 2.3 agregó un método de coincidencia () que le permite usar Criteria .
El ejemplo de Jeremy Hicks puede escribirse así (nota, esto devuelve un ArrayCollection en lugar de una matriz).
public function findActiveFestivals($start, $end)
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where($expr->gte(''start'', $start));
$criteria->andWhere($expr->lte(''end'', $end);
return $this->matching($criteria);
}
Personalmente, no usaría y donde, y uso algunas líneas más para mejorar la legibilidad, así:
public function findActiveFestivals($start, $end)
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where(
$expr->andX(
$expr->gte(''start'', $start),
$expr->lte(''end'', $end)
)
);
return $this->matching($criteria);
}
Usar una cláusula IN es muy simple.
public function findFestivalsByIds($ids)
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where($expr->in(''id'', $ids));
return $this->matching($criteria);
}
La clase Criteria está en el espacio de nombres Common-OR-OR-DBAL de Doctrine, como su ArrayCollection (que ha soportado Criteria por más tiempo que EntityRepository).
Está destinado a ser una forma desacoplada para código no repositorio para crear criterios sofisticados. Entonces debería estar bien usar esta clase fuera del repositorio. QueryBuilder también es compatible con Criteria recientemente. De modo que, incluso cuando se crean consultas más sofisticadas que requieren QueryBuilder, puede usar Criteria para dar flexibilidad al código que no es de la base de datos en lo que solicita.