Symfony2 index of an object sorted by DQL - php

Hi I've done a simple query for a ranking mechanism with the query builder.
$result = $qb
->select('u')
->where('u.status = 1')
->from('PGMainBundle:User', 'u')
->groupBy('u.id')
->addSelect('COUNT(c.id) as HIDDEN nChallenges')
->leftJoin('u.challenges', 'c', 'WITH', 'c.closed = 1' )
->add('orderBy','u.points DESC, nChallenges DESC')
->orderBy('u.points', 'DESC')
->addOrderBy('nChallenges', 'DESC')
->setFirstResult($offset*50)
->setMaxResults(50)
->getQuery()
->getResult();
Now while my ranking mechanism works fine, I'd like to check what loop.index a user with an $id has.
Said this, I don't want to use a foreach loop on the result to do so.
Is there a more optimal way just to return the "position" in the ranking ?
Possibly using the query builder ?

The result should be an array collection so you can get the index of a given element like this :
$result->indexOf($yourelement)
Else if the keys are not in order, but are the id of the entities :
$keys = $result->getKeys();
$id = $yourElement->getId();
$position = array_search($id, $keys);

Related

Can order By date and also if status == "Completed" it should go to end of list in Laravel? [duplicate]

I want to sort multiple columns in Laravel 4 by using the method orderBy() in Laravel Eloquent. The query will be generated using Eloquent like this:
SELECT *
FROM mytable
ORDER BY
coloumn1 DESC, coloumn2 ASC
How can I do this?
Simply invoke orderBy() as many times as you need it. For instance:
User::orderBy('name', 'DESC')
->orderBy('email', 'ASC')
->get();
Produces the following query:
SELECT * FROM `users` ORDER BY `name` DESC, `email` ASC
You can do as #rmobis has specified in his answer, [Adding something more into it]
Using order by twice:
MyTable::orderBy('coloumn1', 'DESC')
->orderBy('coloumn2', 'ASC')
->get();
and the second way to do it is,
Using raw order by:
MyTable::orderByRaw("coloumn1 DESC, coloumn2 ASC");
->get();
Both will produce same query as follow,
SELECT * FROM `my_tables` ORDER BY `coloumn1` DESC, `coloumn2` ASC
As #rmobis specified in comment of first answer you can pass like an array to order by column like this,
$myTable->orders = array(
array('column' => 'coloumn1', 'direction' => 'desc'),
array('column' => 'coloumn2', 'direction' => 'asc')
);
one more way to do it is iterate in loop,
$query = DB::table('my_tables');
foreach ($request->get('order_by_columns') as $column => $direction) {
$query->orderBy($column, $direction);
}
$results = $query->get();
Hope it helps :)
Use order by like this:
return User::orderBy('name', 'DESC')
->orderBy('surname', 'DESC')
->orderBy('email', 'DESC')
...
->get();
Here's another dodge that I came up with for my base repository class where I needed to order by an arbitrary number of columns:
public function findAll(array $where = [], array $with = [], array $orderBy = [], int $limit = 10)
{
$result = $this->model->with($with);
$dataSet = $result->where($where)
// Conditionally use $orderBy if not empty
->when(!empty($orderBy), function ($query) use ($orderBy) {
// Break $orderBy into pairs
$pairs = array_chunk($orderBy, 2);
// Iterate over the pairs
foreach ($pairs as $pair) {
// Use the 'splat' to turn the pair into two arguments
$query->orderBy(...$pair);
}
})
->paginate($limit)
->appends(Input::except('page'));
return $dataSet;
}
Now, you can make your call like this:
$allUsers = $userRepository->findAll([], [], ['name', 'DESC', 'email', 'ASC'], 100);
$this->data['user_posts'] = User_posts::with(['likes', 'comments' => function($query) { $query->orderBy('created_at', 'DESC'); }])->where('status', 1)->orderBy('created_at', 'DESC')->get();

Order joined table with Doctrine

I wrote a query with doctrine where I have joined fruits and vitamins table.
I have sorted vitamins by name ASC but I need to do the same thing with joined table.
I tried
addOrderBy()
, but no luck..
Note: 'c' is Vitamins table.
Everything is returned as it should except fruits are returned with no order..
My code:
$queryBuilder = $this->createQueryBuilder('c')
->select('c', 'ct.name AS fruitName', 'ct.id AS fruitId')
->join('App\Entity\Fruits', 'ct', Expr\Join::WITH, 'ct.id = c.fruitName')
->orderBy('c.name');
$fruits = $queryBuilder->getQuery()->getResult();
$structure = [];
foreach ($fruits as $fruit) {
$structure[$fruit['fruitName']][] = $fruit[0];
}
return $structure;
Try one of these:
Option 1:
$qb->orderBy('c.name ASC, ct.name ASC');
Option 2:
$qb->addOrderBy('c.name', 'ASC')
->addOrderBy('ct.name', 'ASC')

Doctrine QueryBuilder from with subquery

I need to write some complex query builder expression. The sql looks like:
SELECT query,popularity,nb_words
FROM gemini_suggestion
WHERE query IN
(
SELECT * FROM
(
SELECT query
FROM gemini_suggestion
GROUP BY query
HAVING COUNT(query) > 1
) AS subquery
);
The code im stucked at is:
$queryBuilder = $em->createQueryBuilder();
$queryBuilder->select('a')
->from($this->entity['class'], 'a')
->where($queryBuilder->expr()->In('a.query', $subQuery->getDQL()));
$subQuery2 = $em->createQueryBuilder()
->select('b.query')
->from($this->entity['class'], 'b')
->groupBy('b.query')
->having('count(b.query)>1')
;
$subQuery = $em->createQueryBuilder();
$subQuery->select('a')
->from(...)
;
Any help would be nice!
You can try something like this. I'm assuming you have a namespace Entities where you have all your entities classes.
// Subquery to get the queries greater than 1
$subQueryBuilder = $this->entityManager->createQueryBuilder();
$subQueryBuilder->select('gemini_suggestion.query')
->from('Entities\gemini_suggestion', 'gemini_suggestion')
->groupBy('gemini_suggestion.query')
->having($subQueryBuilder->expr()->gt('COUNT(gemini_suggestion.query)', 1));
// Main query where you use the subquery to filter out the records you want
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder->select('query, popularity, nb_words')
->from('Entities\gemini_suggestion', 'gemini_suggestion')
->where($queryBuilder->expr()->in('gemini_suggestion.query', $subQueryBuilder->getDQL()));
$result = $queryBuilder->getQuery()->getResult();
return $result;

Where clause to parents

I have for example two tables: Parent and Children. They have relations many-to-many between each other. Everything is working well, but I don't know how to use where clause in query builder for this.
My code:
$parent = $em->getRepository('AppBundle:Parent')->find(1);
$qb = $em->createQueryBuilder();
$qb->select('c, p')
->from('AppBundle:Children', 'c')
->leftJoin('c.parents', 'p')
->where('p.id = :parent')
->setParameter('parent', $parent)
;
$childrens = $qb->getQuery()->getResult();
This always return me null.
I know - I can use $parent->getChildrens(), but I would like use createQueryBuilder for AppBundle:Children.
How should the where clause look?

How to sort a Laravel query builder result by multiple columns?

I want to sort multiple columns in Laravel 4 by using the method orderBy() in Laravel Eloquent. The query will be generated using Eloquent like this:
SELECT *
FROM mytable
ORDER BY
coloumn1 DESC, coloumn2 ASC
How can I do this?
Simply invoke orderBy() as many times as you need it. For instance:
User::orderBy('name', 'DESC')
->orderBy('email', 'ASC')
->get();
Produces the following query:
SELECT * FROM `users` ORDER BY `name` DESC, `email` ASC
You can do as #rmobis has specified in his answer, [Adding something more into it]
Using order by twice:
MyTable::orderBy('coloumn1', 'DESC')
->orderBy('coloumn2', 'ASC')
->get();
and the second way to do it is,
Using raw order by:
MyTable::orderByRaw("coloumn1 DESC, coloumn2 ASC");
->get();
Both will produce same query as follow,
SELECT * FROM `my_tables` ORDER BY `coloumn1` DESC, `coloumn2` ASC
As #rmobis specified in comment of first answer you can pass like an array to order by column like this,
$myTable->orders = array(
array('column' => 'coloumn1', 'direction' => 'desc'),
array('column' => 'coloumn2', 'direction' => 'asc')
);
one more way to do it is iterate in loop,
$query = DB::table('my_tables');
foreach ($request->get('order_by_columns') as $column => $direction) {
$query->orderBy($column, $direction);
}
$results = $query->get();
Hope it helps :)
Use order by like this:
return User::orderBy('name', 'DESC')
->orderBy('surname', 'DESC')
->orderBy('email', 'DESC')
...
->get();
Here's another dodge that I came up with for my base repository class where I needed to order by an arbitrary number of columns:
public function findAll(array $where = [], array $with = [], array $orderBy = [], int $limit = 10)
{
$result = $this->model->with($with);
$dataSet = $result->where($where)
// Conditionally use $orderBy if not empty
->when(!empty($orderBy), function ($query) use ($orderBy) {
// Break $orderBy into pairs
$pairs = array_chunk($orderBy, 2);
// Iterate over the pairs
foreach ($pairs as $pair) {
// Use the 'splat' to turn the pair into two arguments
$query->orderBy(...$pair);
}
})
->paginate($limit)
->appends(Input::except('page'));
return $dataSet;
}
Now, you can make your call like this:
$allUsers = $userRepository->findAll([], [], ['name', 'DESC', 'email', 'ASC'], 100);
$this->data['user_posts'] = User_posts::with(['likes', 'comments' => function($query) { $query->orderBy('created_at', 'DESC'); }])->where('status', 1)->orderBy('created_at', 'DESC')->get();

Categories