Reputation: 115
I'm trying to build a query with doctrine query builder like this:
$q = $this
->createQueryBuilder('u')
->select('u, r')
->leftJoin('u.roles', 'r')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();`
This code produces 2 queries:
Query 1 is correct
SELECT t0.user_id AS user_id1, t0.username AS username2, t0.salt AS salt3, t0.password AS password4, t0.email AS email5, t0.is_active AS is_active6, t0.created AS created7, t0.updated AS updated8, t0.last_login AS last_login9
FROM users t0
WHERE t0.username = ?
LIMIT 1
Query 2 is not correct:
SELECT t0.role_id AS role_id1, t0.role AS role2
FROM roles t0
INNER JOIN user_role ON t0.id = user_role.role_id
WHERE user_role.user_fk = ?
Query 2 should be:
SELECT t0.role_id AS role_id1, t0.role AS role2
FROM roles t0
INNER JOIN user_role ON t0.role_id = user_role.role_fk
WHERE user_role.user_fk = ?
Entity\Role looks like this:
/**
* @ORM\Table(name="roles")
* @ORM\Entity(repositoryClass="XXX\XXXBundle\Entity\Repository\RoleRepository")
*/
class Role implements RoleInterface
{
/**
* @ORM\Id
* @ORM\Column(name="role_id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $_roleId;
/**
* @ORM\Column(name="role", type="string", length=20, unique=true)
*/
protected $_role;
/**
* @ORM\ManyToMany(targetEntity="User", mappedBy="roles")
* @ORM\JoinTable(name="user_role",
* joinColumns={@ORM\JoinColumn(name="role_fk", referencedColumnName="role_id")})
*/
private $_users;
...
Entity\User looks like this:
class User implements UserInterface, \Serializable
{
/**
* @ORM\Column(name="user_id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $_userId;
...
/**
* @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
* @ORM\JoinTable(name="user_role",
* joinColumns={@ORM\JoinColumn(name="user_fk", referencedColumnName="user_id")})
*/
protected $_roles;
...
The annotation in the Entity\Role code states the column names to use and the SELECT portion of the statement is using the correct names. The WHERE portion of the statement is using the correct column user_role.user_fk, this is defined in the Entity\User code.
How do I stop doctrine using column names that do not exist and use the defined column names for the INNER JOIN part of the statement?
Upvotes: 0
Views: 417
Reputation: 115
I found a solution which works.
Entity\User needs to be altered to include the inverseJoinColumns on the annotation like this:
/**
* @ORM\ManyToMany(targetEntity="Role", inversedBy="_users")
* @ORM\JoinTable(name="user_role",
* joinColumns={@ORM\JoinColumn(name="user_fk", referencedColumnName="user_id")},
* inverseJoinColumns={@ORM\JoinColumn(name="role_fk", referencedColumnName="role_id")})
*/
protected $_roles;
Entity\Role needs to be altered to include the inverseJoinColumns like this:
/**
* @ORM\ManyToMany(targetEntity="User", mappedBy="_roles")
* @ORM\JoinTable(name="user_role",
* joinColumns={@ORM\JoinColumn(name="role_fk", referencedColumnName="role_id")},
* inverseJoinColumns={@ORM\JoinColumn(name="user_fk", referencedColumnName="user_id")})
*/
private $_users;
and the createQueryBuilder code needs to look like this:
$q = $this
->createQueryBuilder('u')
->select('u, r')
->from('XXXXXXBundle:User', 'u')
->leftJoin('u.roles', 'r', \Doctrine\ORM\Query\Expr\Join::ON, 'user_role.role_kf = r.role_id')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();
Upvotes: 1