sql - unir - Constructor de consultas de Doctrine que usa unión interna con condiciones
union mysql dos tablas (2)
Me gustaría construir el siguiente SQL usando el generador de consultas de Doctrine:
select c.*
from customer c
join phone p
on p.customer_id = c.id
and p.phone = :phone
where c.username = :username
Primero lo intenté
$qb->select(''c'')
->innerJoin(''c.phones'', ''p'', Join::ON, $qb->expr()->andx(
$qb->expr()->eq(''p.customerId'', ''c.id''),
$qb->expr()->eq(''p.phone'', '':phone'')
))
->where(''c.username = :username'');
Pero recibo el siguiente error
Error: expected end of string, got ''ON''
Entonces probé
$qb->select(''c'')
->innerJoin(''c.phones'', ''p'')
->where(''c.username = :username'')
->andWhere(''p.phone = :phone'');
que parece estar funcionando. Sin embargo, ¿alguien sabe qué pasa con el primer intento? Me gustaría hacer que el primero funcione, ya que se asemeja más a cómo está estructurado SQL. ¡Gracias por adelantado!
Nota: Sé que también podemos escribir mysql o dql nativos con Doctrine, pero prefiero el generador de consultas.
EDITAR: A continuación está el código completo
namespace Cyan/CustomerBundle/Repository;
use Cyan/CustomerBundle/Entity/Customer;
use Doctrine/ORM/EntityRepository;
use Doctrine/ORM/Query/Expr/Join;
class CustomerRepository extends EntityRepository
{
public function findCustomerByPhone($username, $phone)
{
$qb = $this->createQueryBuilder(''c'');
$qb->select(''c'')
->innerJoin(''c.phones'', ''p'', Join::ON, $qb->expr()->andx(
$qb->expr()->eq(''p.customerId'', ''c.id''),
$qb->expr()->eq(''p.phone'', '':phone'')
))
->where(''c.username = :username'');
// $qb->select(''c'')
// ->innerJoin(''c.phones'', ''p'')
// ->where(''c.username = :username'')
// ->andWhere(''p.phone = :phone'');
$qb->setParameters(array(
''username'' => $username,
''phone'' => $phone->getPhone(),
));
$query = $qb->getQuery();
return $query->getResult();
}
}
Puedes tener una unión explícitamente así:
$qb->innerJoin(''c.phones'', ''p'', Join::ON, ''c.id = p.customerId'');
Pero necesita usar el espacio de nombres de la clase Join from doctrine:
use Doctrine/ORM/Query/Expr/Join;
O si prefieres así:
$qb->innerJoin(''c.phones'', ''p'', Doctrine/ORM/Query/Expr/Join::ON, ''c.id = p.customerId'');
De lo contrario, la clase Join no se detectará y tu script se bloqueará ...
Aquí el constructor del método innerJoin:
public function innerJoin($join, $alias, $conditionType = null, $condition = null);
Puedes encontrar otras posibilidades (no solo unir "ON", sino también "WITH", etc ...) aquí: http://docs.doctrine-project.org/en/2.0.x/reference/query-builder.html#the-expr-class
EDITAR
Piensa que debería ser:
$qb->select(''c'')
->innerJoin(''c.phones'', ''p'', Join::ON, ''c.id = p.customerId'')
->where(''c.username = :username'')
->andWhere(''p.phone = :phone'');
$qb->setParameters(array(
''username'' => $username,
''phone'' => $phone->getPhone(),
));
De lo contrario, creo que estás realizando una combinación de ON y WITH, tal vez el problema.
Voy a responder mi propia pregunta.
- innerJoin debe usar la palabra clave "WITH" en lugar de "ON" (la documentación de Doctrine [13.2.6. Helper methods] es inexacta; [13.2.5. La clase Expr] es correcta)
- no es necesario vincular claves externas en condición de unión ya que ya están especificadas en la asignación de entidad.
Por lo tanto, lo siguiente funciona para mí
$qb->select(''c'')
->innerJoin(''c.phones'', ''p'', ''WITH'', ''p.phone = :phone'')
->where(''c.username = :username'');
o
$qb->select(''c'')
->innerJoin(''c.phones'', ''p'', Join::WITH, $qb->expr()->eq(''p.phone'', '':phone''))
->where(''c.username = :username'');