Laravel orderBy object attribute - php

The 'price' is an object that has an attribute known as list_price.
$products =
Product::with(['child','price','variant','thumbnail','image',
'description'])->
take($recperpage)->get();
I intend to order by list_price attribute. I can't specify the query as follow:
->orderBy('price.list_price','desc')
It doesn't work. Any help? I'm using Laravel 5.3.

If you want to order the query, you have to add a JOIN on the prices tables.
The easier solution is ordering the query result:
$products = Product::with(['child','price','variant','thumbnail','image', 'description'])
->take($recperpage)->get()->sortByDesc('price.list_price');

Related

How do I properly nest queries in cakephp with where clauses?

I'm trying to get an order from the orders table that contains a product url from the product table. I tried using this subquery but cakephp keeps reading the url value s20_ultra as :c0
$temp = $this->Orders->getAssociation('Product')->find()->where(['product.url' => 's20_ultra']);
$result = $this->Orders->find()->where(["productId IN" => $temp]);
echo $result;
Appending firstOrFail() to the end of the first query temp and commenting out the second query result as a test works just fine but when I append it to both I get Cannot convert value of type %s to integer exception.
This would be the normal query of what I'm trying to accomplish:
select * from `order` where productId in (select product.id from product where url = 's20_ultra')
Based on what you've said, I think that the following should work. This assumes that the associations are correctly set up in both directions between Orders and Product. (Note, that's a non-standard naming scheme, it would normally be Products.)
$product = $this->Orders->getAssociation('Product')
->findByUrl('s20_ultra')
->contain(['Orders'])
->firstOrFail();
debug($product->orders);

Laravel 5.6 groupBy on collection doesn't work

GroupBy just doesn't work on collection in Laravel 5.6, it is very annoying when simple things which supposed to work not wirking...
$users = Game::orderBy('game_count', 'desc')->get();
$users_grouped = $users->groupBy('user_id');
As you might guess $users_grouped contains the same collection as $users with the same repeating user_id values.
I don't get why it doesn't work as expected and how to fix it?
At least GROUP BY works with raw DB select hopefully.. But I want to use Eloquent..
You're confusing eloquent's query builder with collections. They are not the same thing.
groupBy on a query builder instance will use an SQL GROUP BY and give one aggregated result for the column(s) you are grouping on.
groupBy on a collection instance will return a new collection that groups all collected items by the given key's value.
https://laravel.com/docs/5.6/collections#method-groupby
If you want to use the query builder's groupBy method, chain it before the get():
$users = Game::orderBy('game_count', 'desc')->groupBy('user_id')->get();
get() executes the query and returns the collection of records.
If you want to group the query by user_id just do the groupBy before the get(), as the following row:
$users = Game::orderBy('game_count', 'desc')->groupBy('user_id')->get();
The rows will be the same. You should make two querys:
$users = Game::orderBy('game_count', 'desc')->get();
$users_grouped = Game::orderBy('game_count', 'desc')->groupBy('user_id')->get();
Temporary solution for this is the raw SQL query:
$users_grouped = DB::select('SELECT COUNT(id) AS theCount, `user_id` from `quiz_games` GROUP BY `user_id` ORDER BY theCount DESC');

OrderBy custom attribute

I've created a custom attribute for a model, and would like to orderBy that that attribute (sortBy is not the solution), after ordering it by that attribute I need to paginate it which is also happening in the query.
This is my current code:
$result = TheEpisode::where('seriesID', $id)->paginate(12);
Before I paginate, I need to orderBy custom attribute - largestNumber ?
Is this possible?
By Laravel.com: The orderBy method allows you to sort the result of the query by a given column. The first argument to the orderBy method should be the column you wish to sort by, while the second argument controls the direction of the sort and may be either asc or desc:
Try this
$result = TheEpisode::where('seriesID', $id)
->orderBy('name', 'desc')
->paginate(12);
References: https://laravel.com/docs/5.3/queries#ordering-grouping-limit-and-offset

Doctrine orderBy on SUM() field with alias

I am trying to do a simple query in doctrine but struggling.
$query->select(array(
'app_title' => 'u.title',
'user_name' => 'u.user_name',
'first_used' => 'MIN(u.creation_time)',
'last_used' => 'MAX(u.stop_time)',
'total_usage' => 'SUM(u.stream_seconds)',
))
->from(self::USAGE_TABLE, 'u')
->orderBy('total_usage', 'DESC');
Obviously I get an error about the column name not being known because Doctrine is using it's own aliases (sclr4).
However, if I try and order by the actual value; SUM(u.stream_seconds), then I get an unexpected bracket in the order by clause, I'm pretty sure SQL doesnt support this.
So, I am simply trying to put data in a table and handle the sorting of the columns. This seems so simple, how do I do it? Any ideas?
You can orderBy the SUM result field by list it in query projection by aliasing result using AS.
If you want to use an aggregate function such as MIN(), MAX(), AVG(), you have to use GROUP BY.
Try simmilar to this, which works perfectly for me (BTW instead of associative array in select method):
$q = $this->em()->createQueryBuilder();
$q->select(['product.id', 'product.title'])
->addSelect('SUM(product.price) AS HIDDEN stat_sum_realised')
->from('ModuleAdmin\Entity\ProductEntity', 'product')
->groupBy('product.id');
$q->orderBy('stat_sum_realised', 'DESC');
Aggregate functions are detailed here (for e.x. for MySQL):
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
As of Doctrine ORM 2.3, you can also use the HIDDEN keyword, which will avoid (in this case) stat_sum_realised from getting hydrated into your resultset.

Order by multiple columns with Doctrine

I need to order data by two columns (when the rows have different values for column number 1, order by it; otherwise, order by column number 2)
I'm using a QueryBuilder to create the query.
If I call the orderBy method a second time, it replaces any previously specified orderings.
I can pass two columns as the first parameter:
->orderBy('r.firstColumn, r.secondColumn', 'DESC');
But I cannot pass two ordering directions for the second parameter, so when I execute this query the first column is ordered in an ascending direction and the second one, descending. I would like to use descending for both of them.
Is there a way to do this using QueryBuilder? Do I need to use DQL?
You have to add the order direction right after the column name:
$qb->orderBy('column1 ASC, column2 DESC');
As you have noted, multiple calls to orderBy do not stack, but you can make multiple calls to addOrderBy:
$qb->addOrderBy('column1', 'ASC')
->addOrderBy('column2', 'DESC');
In Doctrine 2.x you can't pass multiple order by using doctrine 'orderBy' or 'addOrderBy' as above examples. Because, it automatically adds the 'ASC' at the end of the last column name when you left the second parameter blank, such as in the 'orderBy' function.
For an example ->orderBy('a.fist_name ASC, a.last_name ASC') will output SQL something like this 'ORDER BY first_name ASC, last_name ASC ASC'. So this is SQL syntax error. Simply because default of the orderBy or addOrderBy is 'ASC'.
To add multiple order by's you need to use 'add' function. And it will be like this.
->add('orderBy','first_name ASC, last_name ASC'). This will give you the correctly formatted SQL.
More info on add() function. https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html#low-level-api
Hope this helps. Cheers!
you can use ->addOrderBy($sort, $order)
Add:Doctrine Querybuilder btw. often uses "special" modifications of the normal methods, see select-addSelect, where-andWhere-orWhere, groupBy-addgroupBy...
You can use orderBy() followed by an addOrderBy() - nesting several orderBy()'s is not possible, but nesting several addOrderBy()'s also works after the initial orderBy().
Example:
$this->createQueryBuilder('entity')
->orderBy('entity.addDate', 'DESC')
->addOrderBy('entity.id', 'DESC')
The orderBy method requires either two strings or an Expr\OrderBy object. If you want to add multiple order declarations, the correct thing is to use addOrderBy method, or instantiate an OrderBy object and populate it accordingly:
# Inside a Repository method:
$myResults = $this->createQueryBuilder('a')
->addOrderBy('a.column1', 'ASC')
->addOrderBy('a.column2', 'ASC')
->addOrderBy('a.column3', 'DESC')
;
# Or, using a OrderBy object:
$orderBy = new OrderBy('a.column1', 'ASC');
$orderBy->add('a.column2', 'ASC');
$orderBy->add('a.column3', 'DESC');
$myResults = $this->createQueryBuilder('a')
->orderBy($orderBy)
;
The comment for orderBy source code notes: Keys are field and values are the order, being either ASC or DESC.. So you can do orderBy->(['field' => Criteria::ASC]).

Categories