Query Builder / DQL not working with INNER JOIN -

2019-04-09 14:14发布

问题:

I know I have a syntax isse here however I cant figure it out. I'm trying to do a SELECT and INNER JOIN of 5 tables but Symfony is complaining about the Entities in the JOIN are used before being defined.

Actual error is as follows: [Semantical Error] line 0, col 121 near 'I ON C.id = ': Error: Identification Variable MySiteBundle:Items used in join path expression but was not defined before.

Here is the PHP code.

Note: I have shortened this query to two columns, two tables, and one join to keep the question simple and show my point. The actual query is much longer and is producing the same error.

$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
    'select C.name as CName, I.id as IId
    FROM MySiteBundle:Categories C
    INNER JOIN MySiteBundle:Items I ON C.id = I.category_id');
$result = $query->getResult();

Update

As suggested I've done away with the DQL code and am using Query Builder code. I'm getting a very similiar error which says 'Categories c': Error: Class 'Categories' is not defined. My QB code is below.

$em = $this->getDoctrine()->getEntityManager();
$qb = $em->createQueryBuilder()
        ->select('c.name, i.id, i.image, i.name, i.description, m.id, m.quantity, m.value, m.qty_received, m.custom_image, m.custom_name, m.custom_description, u.user1fname, u.user1lname, u.user2fname, u.user2lname')
        ->from('Categories', 'c')
        ->innerJoin('Items', 'i', 'ON', 'c.id = i.category_id')
        ->innerJoin('MemberItems', 'm', 'ON', 'i.id = m.item_id')
        ->innerJoin('User', 'u', 'ON', 'm.memberinfo_id = u.id')
        ->where('u.id = ?', $slug)
        ->orderBy('c.id', 'ASC')
        ->getQuery();

$memberItems = $qb->getResult();

Any suggestions?

回答1:

Louis posted while I was typing. Oh well.

DQL takes care of the join details for you based on your associations. In general, you only need to spell out the FROM class name. Something like:

'select C.name as CName, I.id as IId
FROM MySiteBundle:Categories C
INNER JOIN C.items');

And definitively use query builder.

=============================================================================

Here is an example of using query builder in Symfony 2.

public function getAccounts($params = array())
{
    // Build query
    $em = $this->getEntityManager();
    $qb = $em->createQueryBuilder();

    $qb->addSelect('account');
    $qb->addSelect('accountPerson');
    $qb->addSelect('person');
    $qb->addSelect('registeredPerson');
    $qb->addSelect('projectPerson');

    $qb->from('ZaysoCoreBundle:Account','account');

    $qb->leftJoin('account.accountPersons',  'accountPerson');
    $qb->leftJoin('accountPerson.person',    'person');
    $qb->leftJoin('person.registeredPersons','registeredPerson');
    $qb->leftJoin('person.projects',         'projectPerson');
    $qb->leftJoin('projectPerson.project',   'project');

    if (isset($params['accountId']))
    {
        $qb->andWhere($qb->expr()->in('account.id',$params['accountId']));
    }
    if (isset($params['projectId']))
    {
        $qb->andWhere($qb->expr()->in('project.id',$params['projectId']));
    }
    if (isset($params['aysoid']))
    {
        $qb->andWhere($qb->expr()->eq('registeredPerson.regKey',$qb->expr()->literal($params['aysoid'])));
    }
    $query = $qb->getQuery();

  //die('DQL ' . $query->getSQL());
    return $query->getResult();
}


回答2:

DQL does not use joins like that. They are a bit simplified. However I also found them to be underdocumented.

    $em = $this->getDoctrine()->getEntityManager();
    $query = $em->createQuery(
        'select C.name as CName, I.id as IId
        FROM MySiteBundle:Categories C
        INNER JOIN C.items I');
    $result = $query->getResult();

The actual relation used depends on your model.

I normally use the query builder.

    $em = $this->getEntityManager();
    $request = $em->getRepository('MySiteBundle:Categories');

    $qb = $request->createQueryBuilder('C');
    $query = $qb 
        ->select('C.name, I.id')
        ->innerJoin('C.items', 'I')
        ->getQuery();


回答3:

You may have to check your annotations or yml file to make sure you have your mapping setup correctly for OneToMany, ManyToMany, and ManyToOne.

In your MemberItems Controller or MemberItems Repository put this:

$em = $this->getDoctrine()->getEntityManager();
$qb = $em->createQueryBuilder()
    ->select('c.name, i.id, i.image, i.name, i.description, m.id, m.quantity, m.value, m.qty_received, m.custom_image, m.custom_name, m.custom_description, u.user1fname, u.user1lname, u.user2fname, u.user2lname')
    ->from('m')
    ->innerJoin('m.memberinfo_id', 'u')
    ->innerJoin('m.item_id', 'i')
    ->innerJoin('i.category_id', 'c')
    ->where(
    ->where('u.id = ?', $slug)
    ->orderBy('c.id', 'ASC')
    ->getQuery();

$memberItems = $qb->getResult();