2011-10-11 8 views
11

Tengo un proyecto donde trato con pedidos de clientes. Algunas de esas órdenes se realizan a través de Amazon.com. Así que tengo una entidad Order y una entidad AmazonOrder que la amplía. Una cosa añadida por AmazonOrder es el AmazonOrderId.Doctrine2: Consultas polimórficas: Buscando en las propiedades de las subclases

Tengo un requisito para implementar una función de búsqueda amplia. El usuario puede ingresar algunas cosas en un cuadro de texto y ser utilizado en un conjunto de expresiones en una gran cláusula-donde. Entonces, por ejemplo, si el usuario buscó "111", los resultados incluyen cualquier orden con una ID que comience con 111, cualquier orden que se envíe a códigos postales que comiencen con 111, cualquier orden que se envíe a "111 Main St", etc.

Eso se implementa con una consulta creado por query-builder que tiene una gran expresión orX().

Ahora, me gustaría hacer coincidir todos los pedidos, pero si son AmazonOrder, también coinciden con AmazonOrderId.

Y estoy atascado - Sospecho que puede no ser posible

Así es como estoy construyendo la consulta:

$qb->select('o,s')->from('PMS\Entity\Order', 'o');  
$qb->leftJoin('o.shippingInfo','s'); 
$qb->andWhere('o.status = :status'); 
$qb->setParameter('status',$status); 
$qb->andWhere(
    $qb->expr()->orX(
     $qb->expr()->like('o.id',':query') 
     $qb->expr()->like('s.address',':query') 
     $qb->expr()->like('s.city',':query') 
    ) 
); 
$qb->setParameter('query',$userQuery .'%'); 

$orders = $qb->getQuery()->getResult(); 

Y no puedo encontrar la manera de añadir una condición que dice, más o menos, "OR (Order es AmazonOrder AND AmazonOrderId LIKE '$ userQuery%')"

¿Alguien tiene alguna idea? ¿O una forma de manejar esto, o al menos una confirmación de que no es posible de esta manera?

Respuesta

21

Aquí hay otra solución que funcione para mí con Doctrina 2.4:

$qb->select('o') 
    ->from('Order', 'o') 
    ->leftJoin('AmazonOrder', 'ao', 'WITH', 'o.id = ao.id') 
    ->andWhere('o.id like :query or ao.amazonOrderId like :query') 
    ->setParameter('query', $someQuery); 

que acaba de salir a unirse a la entidad en la subclase específica de la misma. (Puede adaptar mi consulta simple a su caso de uso.)

He intentado esto exactamente una vez, pero parece que funciona.

+0

Esto funciona bien incluso para entidades con claves compuestas. – Wilt

+0

¡Si pudiera votar esta respuesta una vez más, lo haría! – Wilt

+0

¡Gracias por esto! En DQL para el registro: SELECCIONAR o FROM Order LEFT JOIN AmazonOrder ao WITH o.id = ao.id – omgitsdrobinoha

2

Hm, tuve problemas similares en mi último proyecto de doctrina.

Una vez era solo un campo, así que lo moví a la clase principal, no la mejor solución, pero funcionó. En otro caso, había demasiadas propiedades, por lo que estas habrían atestado la clase principal. Hice una consulta sql nativa para buscar y obtener los identificadores de registro y luego usé un dql WHERE IN (...) para obtener las entidades.

Un compromiso podría ser la doctrina ResultSetMapping que puede asignar una consulta SQL nativo de entidades directamente, aunque cada vez que trabajé con él me pareció bastante torpe a emplear y la sobrecarga de dos consultas (fetch identificadores de & ir a buscar ENTIDADES) como delineado arriba para ser negligetable.

Tal vez podría lograr algo con el operador INSTANCEOF en su cláusula WHERE, aunque no creo que la doctrina sea lo suficientemente inteligente como para reconocerlo de la manera que desee.

+0

Gracias Max. Por el momento, he evitado el problema al trabajar con UI. No es óptimo, y volveré a visitarlo pronto. Realmente me gustaría evitar mover cosas a la superclase. Parece que tenía razón al pensar que no había una solución directa. Si encuentro algo inteligente cuando vuelvo a tratar el tema, se lo haré saber. – timdev

+0

Véase también http://stackoverflow.com/a/19942431/560114 –

Cuestiones relacionadas