Subquery in doctrine2 notIN Function
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.
Join subquery with doctrine 2 DBAL
I've found a solution by adapting this DQL example to DBAL. The trick is to get the raw SQL of the subquery, wrap it in brackets, and join it. Parameters used in the subquery must be set in the main query:
$subSelect = $connection->createQueryBuilder()
->select(array('userSurveyID', 'MIN(timestamp) timestamp'))
->from('user_survey_status_entries')
// Instead of setting the parameter in the main query below, it could be quoted here:
// ->where('status = ' . $connection->quote(UserSurveyStatus::ACCESSED))
->where('status = :status')
->groupBy('userSurveyID');
$select = $connection->createQueryBuilder()
->select($selectColNames)
->from('user_surveys', 'us')
// Get raw subquery SQL and wrap in brackets.
->leftJoin('us', sprintf('(%s)', $subSelect->getSQL()), 'firstAccess', 'us.userSurveyID = firstAccess.userSurveyID')
// Parameter used in subquery must be set in main query.
->setParameter('status', UserSurveyStatus::ACCESSED)
->where('us.surveyID = :surveyID')->setParameter('surveyID', $surveyID);
Error with subquery in doctrine2 query builder
This issue is about objects and references in PHP.
When you do $subquery = $query;
, $query
being an object, you simply have $subquery
pointing to the same value.
A PHP reference is an alias, which allows two different variables to
write to the same value. As of PHP 5, an object variable doesn't
contain the object itself as value anymore. It only contains an object
identifier which allows object accessors to find the actual object.
When an object is [...] assigned to another
variable, the different variables are not aliases: they hold a copy of
the identifier, which points to the same object.
Reference: http://us1.php.net/manual/en/language.oop5.references.php
It means in your code that when you write this:
$subquery
->select('f.following')
->from('ApiBundle:Follow', 'f')
->where('f.follower = :follower_id')
->setParameter('follower_id', $id)
;
This is equivalent to:
$query
->select('f.following')
->from('ApiBundle:Follow', 'f')
->where('f.follower = :follower_id')
->setParameter('follower_id', $id)
;
So when at the end you call:
$query->andWhere(
$query->expr()->notIn('c.id', $subquery->getDQL())
);
You are using 2 times the same object pointed by 2 different variables ($query === $subquery
).
To solve this issue, you can either use:
$query = $this->getEntityManager()->createQueryBuilder();
$subquery = $this->getEntityManager()->createQueryBuilder();
Or the clone
keyword:
$query = $this->getEntityManager()->createQueryBuilder();
$subquery = clone $query;
Symfony2 Doctrine NotIn issue
Looks like I figured out how to do it this way, through this post: Subquery in doctrine2 notIN Function. I use the getDQL function on the notin query and make sure that all my aliases don't coincide with the regular query ones.
public function loadCompleted()
{
$notIn = $this->getEntityManager()->createQueryBuilder()
->select('DISTINCT j')
->from($this->getEntityName(), 'j')
->join('NucleoManagerBundle:JobStatus', 'js', Join::WITH, 'j.jobStatus = js.id')
->join('NucleoManagerBundle:Task', 't', Join::WITH, 't.job = j.id')
->join('NucleoManagerBundle:TaskStatus', 'ts', Join::WITH, 't.taskStatus = ts.id');
$notIn->where('ts.draft = 1')
->orWhere('ts.pending = 1')
->orWhere('ts.depending = 1')
->orWhere($notIn->expr()->andX(
$notIn->expr()->eq('ts.draft', $notIn->expr()->literal(false)),
$notIn->expr()->eq('ts.completed', $notIn->expr()->literal(false)),
$notIn->expr()->eq('ts.pending', $notIn->expr()->literal(false)),
$notIn->expr()->eq('ts.invoiced', $notIn->expr()->literal(false)),
$notIn->expr()->eq('ts.cancelled', $notIn->expr()->literal(false)),
$notIn->expr()->eq('ts.depending', $notIn->expr()->literal(false))
));
$query = $this->getEntityManager()->createQueryBuilder()
->select('job')
->from($this->getEntityName(), 'job')
->join('NucleoManagerBundle:JobStatus', 'jstatus', Join::WITH, 'job.jobStatus = jstatus.id')
->where('job.billable = 1')
->andWhere('job.invoiced = 0')
->andWhere('job.template = 0')
->andWhere('jstatus.invoiced = 0')
->andWhere('jstatus.cancelled = 0');
$query->andWhere($query->expr()->notIn('job.id', $notIn->getDQL()));
return $query->getQuery()->getResult();
}
doctrine not exists subquery
You can achieve it with something like this:
....
// construct a subselect joined with an entity that have a relation with the first table as example user
$sub = $this->createQueryBuilder();
$sub->select("t");
$sub->from("AnotherEntity","t");
$sub->andWhere('t.user = j.id');
// Your query builder:
$qb->andWhere($qb->expr()->not($qb->expr()->exists($sub->getDQL())));
Hope this help
Related Topics
How to Can Post a Multiple Photos via Facebook API
Is PHP Str_Word_Count() Multibyte Safe
Redirect with PHP After Ajax Call
Display Possible Combinations of String
How to Open a Link in Private Browsing Mode
Returning Multiple Rows with MySQLi and Arrays
Why Does This PHP Code Just Echo "Array"
PHP File Upload, How to Restrict File Upload Type
A Conditional Element Inside an Array(...) Construct
Issue with Laravel Rules & Regex (Or) Operator
Array_Key_Exists Is Not Working
How to Pass Data Between Pages in PHP
Split Keywords for Post PHP MySQL
PHP String Function to Get Substring Before the Last Occurrence of a Character
Selecting All Columns That Start with Xxx Using a Wildcard