I have following code in my Repository
// ProductBundle/Repository/ProductRepository.php
$qb->where($qb->expr()->eq('afp.id', 15));
$qb->andWhere($qb->expr()->eq('afp.id', 14));
return $qb
->select('a', 'afp')
->leftJoin('a.productFields', 'afp')
->getQuery()
->getResult();
But I always get null return, but I want to get products which have both productFields (so orWhere is not good).
You want to use MEMBER OF instead of comparing id. Otherwise, you're looking for a record that has two different id values, which of course isn't possible.
This will do what you want:
$qb->where($qb->expr()->isMemberOf(15, 'a.productFields'));
$qb->andWhere($qb->expr()->isMemberOf(14, 'a.productFields'));
Try something like this (Symfony 5):
$qb->andWhere(':c MEMBER OF a.productFields');
$qb->setParameter('c', 15);
Related
I have the following query:
$query = $qb->select('p')
->from(get_class($page), 'p')
->innerJoin('p1.translations', 't')
->groupBy('p.id')
->addGroupBy('t.id')
->getQuery();
Doctrine returns the above like:
Page entity -> [translation 1, translation 2, translation 3]
But I want the result like:
Page entity 1 -> translation 1
Page entity 1 -> translation 2
Page entity 1 -> translation 3
Does anyone know how I can do this? I want to return a list of entities.
First of all, both groupBy are completely superfluous, assuming both id fields you are grouping by are the primary keys of their respective tables. For any given (p.id, t.id) combination there will only be at most one result, whether you are grouping or not.
Second, even though you are joining the the translations table, you are not fetching any data from it (t is absent from your ->select()). It just appears that way since doctrine "magically" loads the data in the background when you call $page->getTranslations() (assuming your getter is called that way).
Third, your issue isn't with the groupBy. You are completely misunderstanding what an ORM actually does when hydrating a query result. The SQL query that doctrine generates from your code will actually return results in a fashion just like you expect, with "Page entity 1" repeated multiple times.
However, now comes the hydration step. Doctrine reads the first result row, builds a "Page entity 1" and a "Translation 1" entity, links them and adds them to it's internal entity registry. Then, for the second result, Doctrine notices that it has already hydrated the "Page entity 1" object and (this is the crucial part!) reuses the same object from the first row, adding the second translation to the ->translation collection of the existing object. Even if you read the "Page entity 1" again in a completely different query later in your code, you still get the same PHP object again.
This behaviour is at the core of what Doctrine does. Basically, any table row in the database will always be mirrored by a single object on the PHP side, no matter how often or in what way you actually read it from the database.
To summarize, your query should look like this:
$query = $qb->select('p, t')
->from(get_class($page), 'p')
->innerJoin('p.translations', 't')
->getQuery();
If you really need to iterate over all (p, t) combinations, do so with nested loops:
foreach ($query->getResult() as $p) {
foreach ($p->getTranslations() as $t) {
// do something
}
}
EDIT: If your relationship is bidirectional, you could also turn your query around:
$query = $qb->select('t, p')
->from('My\Bundle\Entity\Translation', 't')
->innerJoin('t.page', 'p')
->getQuery();
Now in your example you actually get 3 results that you can iterate over in a single foreach(). You would still only get a single "Page entity 1" object, with all the translations in the query result pointing to it.
I want to groupBy() task using Laravel Eloquent. I have searched Internet and didn't find anything with eloquent.
some people used groupBy() query with Query Builder like this link
But I want to create query like this style:
Task::select('id')->groupBy('category_id')->count();
This code just return only count of first category_id. But I want count of all the category_id.
Native Collection alternative (grouped by php, not mysql). It's a nice option when you have the Collection as variable already assigned. Of course is less optimal than mysql grouping in most cases.
$tasks->groupBy('category_id')->map->count();
You should add the count to the select function and use the get function to execute the query.
Task::select('id', \DB::raw("count(id)"))->groupBy('category_id')->get();
The \DB::raw() function makes sure the string is inserted in the query without Laravel modifying its value.
More simple:
Task::select('id')->groupBy('category_id')**->get()**->count();
You can do something like this:
return DB::table('offers')->select('*', DB::raw('count('.$field.') as total_count'))->groupBy($field)->get();
I overrode the count() method in my model. Could be something like:
public function count($string = '*'){
$tempmodel = new YourModel();
return $tempmodel ->where('id',$this->id)->where('category_id',$this->category_id)->count($string);
}
This gave me exactly the behavior of count() I was looking for.
Worked for me as
we need to select one column like 'category_id' or 'user_id' and then
count the selected column on get()
Task::select('category_id')
->where('user_id',Auth::user()->id)
->groupBy(['category_id'])
->get()
->count();
This works for me.
output:
return $email_trackers = EmailTracker::get()->groupBy('campaign_id')->map->count();
{
"6": 2
}
I want to use symfony's query builder and add a where to the last item in an array collection
$query = $em->getRepository('RlBookingsBundle:Booking')->createQueryBuilder('b')
->select('b, v, c, ca, q')
->leftJoin('b.vehicle', 'v')
->leftJoin('b.customer', 'c')
->leftJoin('c.address', 'ca')
->leftJoin('b.quote', 'q')
->leftJoin('b.history', 'h') //This is an array collection
->orderBy('b.edited', 'DESC')
;
I want to use only the latest value from history as it is a log but only the most recent entry is valid
->where('h.status IN (:status)')
->setParameter('status', [7]);
Will return all results with h.status = 7 but I would like it to only query the most recent result. Is there anyway to do this?
I tried a groupby on the history field but this seems to groupby with data from the first entry, even if I add an orderby to it.
If the results you get are already ok, but you only want the first, you could just use
...
->setMaxResults(1)
...
If you want to order by history ID desc, you may want to add another orderBy clause before the existing one
...
->orderBy('h.id', 'DESC')
->orderBy('b.edited', 'DESC')
...
If it's more complex than that, I strongly suggest you perform a separate query to get the desired record(s) from history, and THEN use it as a filter, instead of the leftJoin.
I'm trying to make a quite complex query with the QueryBuilder of Doctrine 2.
I would like to SELECT a SUM of elements FROM the result of a subquery.
Here is what I try for now, trying to guess the use of all() method (see : http://doctrine-orm.readthedocs.org/en/latest/reference/query-builder.html)
$qb = $this->createQueryBuilder('stuff');
$qb->select('SUM(perf_final.perf_ratio) AS stuff_perf, date AS date')
->from($qb->expr()->all($qb2->getDql()), 'perf_final')
->groupBy('YEAR(perf_final.date)')
->addGroupBy('MONTH(perf_final.date)');
But, Symfony tells me that ALL is an undefined method...
Any ideas of what could be a good practice to do what I need?
Thx,
I have two Entities with relation OneToMany, Project and Services. Now i want to remove all the services by project_id.
First attempt:
$qb = $em->createQueryBuilder();
$qb->delete('Services','s');
$qb->andWhere($qb->expr()->eq('s.project_id', ':id'));
$qb->setParameter(':id',$project->getId());
This attempt fails with the Exception Entity Service does not have property project_id. And it's true, that property does not exists, it's only in database table as foreign key.
Second attempt:
$qb = $em->createQueryBuilder();
$qb->delete('Services','s')->innerJoin('s.project','p');
$qb->andWhere($qb->expr()->eq('p.id', ':id'));
$qb->setParameter(':id',$project->getId());
This one generetate a non valid DQL query too.
Any ideas and examples will be welcome.
You're working with DQL, not SQL, so don't reference the IDs in your condition, reference the object instead.
So your first example would be altered to:
$qb = $em->createQueryBuilder();
$qb->delete('Services', 's');
$qb->where('s.project = :project');
$qb->setParameter('project', $project);
If you really can't get project object and you have to handle only with id you can use this.
Citation from doctrine documentation:
There are two possibilities for bulk deletes with Doctrine. You can either issue a single DQL DELETE query or you can iterate over results removing them one at a time. (Below I paste only first solution)
DQL Query
The by far most efficient way for bulk deletes is to use a DQL DELETE query.
Example that worked in my project
$q = $em->createQuery('delete from AcmeMyTestBundle:TemplateBlock tb where tb.template = '.intval($templateId));
$numDeleted = $q->execute();
In entity TemplateBlock I have property called template which is mapped to template_id in db.
But I agree that highly preferred way of doing it is using objects.