Codeigniter and doctrine join three tables - php

Hello there I am trying to join 3 tables in doctrine codeigniter i have successfully join two tables but have problem in joining the third one.
Here is my codeigniter active record Query. I want to handle this query in doctrine
$query = $this->db->select('table1.name, table3.date')
->from('table1')
->join('table2', 'table2.id = table1.Uid')
->join('table3', 'table3.id = table1.Rid')
->where('table1.Uid', $Uid)
->get();
return $query->result();
This is my Doctrine query builder query where i join two tables successfully.
$qb = $this->em->createQueryBuilder();
$query = $qb->select('t1, t2')
->from('table1', 't1')
->join('table2', 't2')
// ->join('table3', 't3')
->where('t1.Uid = :Uid')
->andwhere('t2.Yid = :Yid')
->setParameters(array('Uid'=> $Uid, 'Yid' => $user_id))
->getQuery()
->getResult();

Try using the following code, seems like your syntax is not correct.
$qb = $this->em->createQueryBuilder();
$query = $qb->select('t1.name', 't2.name')
->from('table1', 't1')
->leftJoin('t1', 'table2', 't2', 't2.id = t1.Uid')
->leftJoin('t1', 'table3', 't3', 't3.id = t1.Rid')
->where('t1.Uid = :Uid')
->andwhere('t2.Yid = :Yid')
->setParameters(array('Uid'=> $Uid, 'Yid' => $user_id))
->getQuery()
->getResult()
More information about Constructing a new QueryBuilder object

Related

How to implement subqueries in Symfony2 with Doctrine?

I need to count the number of items returned in the subquery. If I write the subquery how DQL - all good, but if I try to build a query via QueryBuilder - I get an error.
Subquery DQL:
$qb3 = $this->createQueryBuilder('c')
->select('COUNT(c.id)')
->where('c.id IN (SELECT cl.id FROM Acme\AppBundle\Entity\ClassC cl INNER JOIN Acme\AppBundle\Entity\ClassP p WHERE p.var1 = :var1 AND p.var2 = cl.id GROUP BY cl.id)')
->setParameter('var1', $var);
Subquery via QueryBuilder:
$qb = $this->createQueryBuilder('c');
$qb->select('COUNT(c.id)')
->where(
$qb->expr()->in(
'c.id',
$this->createQueryBuilder('cl')
->select('cl.id')
->innerJoin('Acme\AppBundle\Entity\ClassP', 'p')
->where('p.var1 = :var1')
->setParameter('var1', $var)
->andWhere('p.var2 = cl.id')
->groupBy('cl.id')
->getDQL()
)
);
Both versions return the same DQL.
Error:
screen
Try to move setParameter() to main level of query.
$qb = $this->createQueryBuilder('c');
$qb->select('COUNT(c.id)')
->where(
$qb->expr()->in(
'c.id',
$this->createQueryBuilder('cl')
->select('cl.id')
->innerJoin('Acme\AppBundle\Entity\ClassP', 'p')
->where('p.var1 = :var1')
->andWhere('p.var2 = cl.id')
->groupBy('cl.id')
->getDQL()
)
)
->setParameter('var1', $var);

Convert sql to doctrine orm in aend framework

I have a query which looks like below:
SELECT *
FROM mydb.users
left join mydb.job on
users.id = job.userid;
Now I am using doctrine orm in querying database but I am newbie here.
What I have done so far is below but it doesn't work as expected.
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$qb->select(array('a', 'c'))
->from('Admin\Entity\User', 'a')
->leftJoin('a.id', 'c');
$query = $qb->getQuery();
$results = $query->getResult();
return $results;
you do not need the from clause and array from clause select
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder('u');
$qb->select('u', 'j')
->leftJoin('u.jobs', 'j')
$query = $qb->getQuery();
$results = $query->getResult();
return $results;
it is mandatory that your users entity contains a "one to many" jobs for the attribute.
trick to display the SQL output :
var_dump($qb->getQuery()->getSQL());

symfony doctrine complex querybuilder

Maybe something simple but my query builder doesn't return what I want. I would something like ... where ... AND (.... OR ....)
I try to read the doctrine doc but, I'm not fluent english so I don't really understand the doctrine doc (maybe a translation in french is available ?).
<?php
// $qb instanceof QueryBuilder
$qb->select(array('u')) // string 'u' is converted to array internally
->from('User', 'u')
->where($qb->expr()->orX(
$qb->expr()->eq('u.id', '?1'),
$qb->expr()->like('u.nickname', '?2')
))
->orderBy('u.surname', 'ASC'));
Here is my MySQL test code that work
select count(distinct(u.username)) from fos_user u join users_accounts ua ON u.id=ua.user_id join account acc ON acc.id = ua.account_id where u.id=48 and (acc.id=2 OR acc.id=5)
Here is the query builder :
I use a service because I had to use this functionality more than once.
/**
* Check if User exists in one of the connected user (Admin or SupAdmin) accounts
* argument : userID
*
*/
public function userExists($userID)
{
// Return accounts (array)
$accounts = $this->accountManager->listAccountsByConnectedUser();
$repository = $this->em->getRepository('CMiNewsBundle:User');
$qb = $repository->createQueryBuilder('u');
$query = $qb
->select('count(u)')
->join ('u.accounts', 'acc')
->where('u.id = :userID')
->andwhere('acc.id = :accountID')
->setParameters(array(
'userID' => $userID,
'accountID' => $accounts[0]->getId(),
));
if (count($accounts) > 1) {
$accountMax = count($accounts);
for($acc=1; $acc<$accountMax; $acc++)
{
$query->orWhere('acc.id = :accountID_'.$acc.'')->setParameter('accountID_'.$acc.'', $accounts[$acc]->getId());
}
};
$query = $query->getQuery();
$result = $query->getResult();
return $result;
}
Thank you for your advices
You can rewrite your query as using IN() in mysql like below
SELECT
COUNT(DISTINCT (u.username))
FROM
fos_user u
JOIN users_accounts ua
ON u.id = ua.user_id
JOIN account acc
ON acc.id = ua.account_id
WHERE u.id = 48
AND acc.id IN(2,5) /* this is equivalent to acc.id = 2 or acc.id = 5 */
The current query for doctrine you are running is ignoring your and condition like if you have 2 accounts ids query will be
WHERE u.id = 48 AND acc.id = 2 OR acc.id = 5
So it will give records for acc.id = 5 and u.id can be any other id
For doctrine query you can rewrite your code as below,You have to build an array of account ids and pass this array in your IN() clause
public function userExists($userID)
{
// Return accounts (array)
$accounts = $this->accountManager->listAccountsByConnectedUser();
$repository = $this->em->getRepository('CMiNewsBundle:User');
$qb = $repository->createQueryBuilder('u');
$accounts=array();
$accounts[]=$accounts[0]->getId();
if (count($accounts) > 1) {
$accountMax = count($accounts);
for ($acc = 1; $acc < $accountMax; $acc++) {
$accounts[]=$accounts[$acc]->getId();
}
}
$query = $qb
->select('count(u) as your_count')
->join('u.accounts', 'acc')
->where('u.id = :userID')
->andwhere('acc.id IN(:accountID)')
->setParameters(array(
'userID' => $userID,
'accountID' => $accounts,
));
$query = $query->getQuery();
$result = $query->getResult();
return $result;
}

Symfony Doctrine QueryBuilder

I try to convert this query to the querybuilder:
SELECT *, landingpages_content.id as cid FROM `landingpages_content` LEFT JOIN content ON landingpages_content.content_id = content.id WHERE content.enabled = 1 AND landingpages_content.landingpage_id = ? ORDER BY landingpages_content.`order`
This is my QueryBuilder code:
$queryBuilder
->select('*, landingpages_content.id as cid')
->from('landingpages_content', 'landingpages_content')
->leftJoin('landingpages_content.content_id', 'content.id', null)
->where('content.enabled = 1')
->andWhere('landingpages_content.landingpage_id = :id')
->setParameter('id', $id)
->orderBy('landingpages_content.`order`', 'ASC');
It returns
InvalidArgumentException: The query builder cannot have joins.
You are using leftJoin method wrong. Try something like this:
$queryBuilder
->select('*, landingpages_content.id as cid')
->from('landingpages_content', 'landingpages_content')
->leftJoin('landingpages_content.content', 'content', 'ON', 'landingpages_content.content_id = content.id')
->where('content.enabled = 1')
->andWhere('landingpages_content.landingpage_id = :id')
->setParameter('id', $id)
->orderBy('landingpages_content.order', 'ASC');

Subquery in doctrine2 notIN Function

I'd like to select members who are not in specific service. I have 3 tables :
membre
service
membre_service (relation between membre and service)
I'm using doctrine 2 and in SQL my query is :
SELECT m.* FROM membre m WHERE m.`id` NOT IN (
SELECT ms.membre_id FROM membre_service ms WHERE ms.service_id != 29
)
In Doctrine, I do :
$qb = $this->_em->createQueryBuilder();
$qb2 = $qb;
$qb2->select('m.id')
->from('Custom\Entity\MembreService', 'ms')
->leftJoin('ms.membre', 'm')
->where('ms.id != ?1')
->setParameter(1, $service);
$qb = $this->_em->createQueryBuilder();
$qb->select('m')
->from('Custom\Entity\Membre', 'm')
->where($qb->expr()->notIn('m.id', $qb2->getDQL())
);
$query = $qb->getQuery();
//$query->useResultCache(true, 1200, __FUNCTION__);
return $query->getResult();
I got the following error :
Semantical Error] line 0, col 123 near 'm WHERE ms.id': Error: 'm' is already defined.
The same alias cannot be defined 2 times in the same query
$qb = $this->_em->createQueryBuilder();
$qb2 = $qb;
$qb2->select('m.id')
->from('Custom\Entity\MembreService', 'ms')
->leftJoin('ms.membre', 'm')
->where('ms.id != ?1');
$qb = $this->_em->createQueryBuilder();
$qb->select('mm')
->from('Custom\Entity\Membre', 'mm')
->where($qb->expr()->notIn('mm.id', $qb2->getDQL())
);
$qb->setParameter(1, $service);
$query = $qb->getQuery();
return $query->getResult();
Ideally you should use many-to-many relation for your entity, in this case your query is going to be much simpler.
Actually if you are using the Symfony2 repository class you could also do the following:
$in = $this->getEntityManager()->getRepository('Custom:MembreService')
->createQueryBuilder('ms')
->select('identity(ms.m)')
->where(ms.id != ?1);
$q = $this->createQueryBuilder('m')
->where($q->expr()->notIn('m.id', $in->getDQL()))
->setParameter(1, $service);
return $q->getQuery()->execute();
You can use (NOT) MEMBER OF:
<?php
$query = $em->createQuery('SELECT m.id FROM Custom\Entity\Membre WHERE :service NOT MEMBER OF m.services');
$query->setParameter('service', $service);
$ids = $query->getResult();
See the documentation for more examples.

Categories