Question

I'm trying to get a User and his associated Role using DQL queries. In order to check why I can't get the user roles using symfony2 tutorial.

http://symfony.com/doc/current/cookbook/security/entity_provider.html

These are the tables...

User table:

+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| username | varchar(255) | NO   |     | NULL    |                |
| password | varchar(255) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+

user_role table:

+---------+---------+------+-----+---------+-------+
| Field   | Type    | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| user_id | int(11) | NO   | PRI | NULL    |       |
| role_id | int(11) | NO   | PRI | NULL    |       |
+---------+---------+------+-----+---------+-------+

Role table:

+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| role  | varchar(255) | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+

and this is the method I'm trying to implement inside UserRepository:

public function findRolesByUsername($name) {
    $em = $this->getEntityManager();
    $query = $em->createQuery('SELECT u.username, r.role 
                               FROM TestLoginBundle:User u
                               JOIN TestLoginBundle:Role r
                               WHERE u.username = :user')
                               ->setParameter('user', $name);
    $result = $query->getResult();

    return $result;
}

Getting this result...

+----------+------------+
| username | role       |
+----------+------------+
| admin    | ROLE_ADMIN |
| admin    | ROLE_USER  |
+----------+------------+

Wanting this one...

+----------+------------+
| username | role       |
+----------+------------+
| admin    | ROLE_ADMIN |
+----------+------------+

I know how to get this result using SQL sentence, but not with DQL.

SQL query:

SELECT u.username, r.role 
FROM User u 
JOIN user_role ur 
ON u.id = ur.user_id 
JOIN Role r 
ON ur.role_id = r.id;
Was it helpful?

Solution

The problem seems to reside in your Entities. You need to add proper annotations to your entities, if you want DQL to work they way it was designed to work.

It seems like you're facing the classic One-To-Many, Unidirectional problem:

For example:

Users.php:

<?php

/**
 *@ORM\Table("Users")
 *@ORM\Entity
 */

class Users {
    /**
     * @ORM\ManyToMany(targetEntity="Role")
     * @ORM\JoinTable(name="users_roles",
     *      joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="role_id", referencedColumnName="id")}
     *      )
     */
    private $roles;

    public function __construct() {
        $this->roles = new ArrayCollection();
    }
}

Then it should be just a matter of writing a DQL like:

$query = $em->createQuery('
SELECT
    u.username, u.roles.role
FROM
    TestLoginBundle:User u
WHERE
    u.username = :user
')->setParameter('user', $name);

In order to get the results you want.

Read the following page in Doctrine's documentation:

http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html

They provide more in depth and thorough examples, than the one shown above. However, if you plan to use these examples in Symfony. Remember to prepend @ORM\ to all the annotations shown in Doctrine's docs.

For example, if Doctrine's documentation tells you to use:

/**
 * ManyToMany(targetEntity="Role")
 */

Then in symfony, you have to write it like:

/**
 * @ORM\ManyToMany(targetEntity="Role")
 */

Otherwise, it won't work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top