Here is target sql query:
...... order by field1 asc, price_index.min_price desc
And here is my code
$productCollection->getCollection()
->setOrder('field1', 'asc')
->setOrder('price', 'desc')
However in my result price always is first ordering field. can anyone help me, Please ? Thank you so much
$collection->getSelect()
->order('field1 asc');
or sort by multiple:
$collection->getSelect()
->order(array('field1 asc', 'price desc'));
To sort using multiple Fields, you can chain calls to the Collection’s method addAttributeToSort()
$productCollection->getCollection()
->addAttributeToSort('field1', 'asc')
->addAttributeToSort('price', 'desc');
on custom resource collection, use addOrder:
Mage::getModel('module/model')->getCollection()
->addOrder('first', 'ASC')
->addOrder('second', 'DESC')
->addOrder('other', 'DESC');
Using:
productCollection->getSelect()->reset(Zend_Db_Select::ORDER);
Then:
productCollection->getSelect()
->order(.......)
That code will resolve this problem ^ ^
To sort multiple fields you can use
$collection = Mage::getModel(‘module/model_name’)->getCollection()
->addAttributeToSort(‘order’, ‘ASC’)
->addAttributeToSort(‘last_name’, ‘ASC’)
->addAttributeToSort(‘first_name’, ‘ASC’);
Related
i want to get all user data and sort by ascending order then select required columns
$drivers = Driver::all()
->select('id','first_name','last_name','phone_number','registration_id')
->get();
now i'm getting all the data
thank you
In this case, remove all() and add an orderBy():
$drivers = Driver::select('id','first_name','last_name','phone_number','registration_id')
->orderBy('the-order-column', 'asc or desc')
->get();
The methods all() and get() do the same thing, except from that you can't modify the query using all() (like adding orderBy()).
Laravels documentation on orderBy(): https://laravel.com/docs/5.3/queries#ordering-grouping-limit-and-offset
To sort results, just use OrderBy.
For example, if you want to sort by first_name, use :
$drivers = Driver::select('id','first_name','last_name','phone_number','registration_id')
->orderBy('first_name', 'asc')
->get();
change 'asc' with 'desc' if you want descending order.
And don't use All() if you don't want everything.
I'm using a Roles package (similar to entrust). I'm trying to sort my User::all() query on roles.id or roles.name
The following is all working
User::with('roles');
This returns a Collection, with a Roles relation that also is a collection.. Like this:
I'm trying to get all users, but ordered by their role ID.
I tried the following without success
maybe because 'roles' returns a collection? And not the first role?
return App\User::with(['roles' => function($query) {
$query->orderBy('roles.id', 'asc');
}])->get();
And this
return App\User::with('roles')->orderBy('roles.id','DESC')->get();
None of them are working. I'm stuck! Can someone point me in the right direction please?
You can take the help of joins like this:
App\User::join('roles', 'users.role_id', '=', 'roles.id')
->orderBy('roles.id', 'desc')
->get();
Hope this helps!
You can make accessor which contains role id or name that you want to sort by.
Assume that the accessor name is roleCode. Then App\User::all()->sortBy('roleCode') will work.
Here's the dirty trick using collections. There might be a better way to achieve this(using Paginator class, I guess). This solution is definitely a disaster for huge tables.
$roles = Role::with('users')->orderBy('id', 'DESC')->get();
$sortedByRoleId = collect();
$roles->each(function ($role) use($sorted) {
$sortedByRoleId->push($role->users);
});
$sortedByRoleId = $sortedByRoleId->flatten()->keyBy('id');
You can sort your relations by using the query builder:
notice the difference with your own example: I don't set roles.id but just id
$users = App\User::with(['roles' => function ($query) {
$query->orderBy('id', 'desc');
}])->get();
See the Official Laravel Docs on Constraining Eager Loading
f you want to order the result based on nested relation column, you must use a chain of joins:
$values = User::query()->leftJoin('model_has_roles', function ($join)
{
$join>on('model_has_roles.model_id', '=', 'users.id')
->where('model_has_roles.model_type', '=', 'app\Models\User');})
->leftJoin('roles', 'roles.id', '=', 'model_has_roles.role_id')
->orderBy('roles.id')->get();
please note that if you want to order by multiple columns you could add 'orderBy' clause as much as you want:
->orderBy('roles.name', 'DESC')->orderby('teams.roles', 'ASC') //... ext
check my answer here:
https://stackoverflow.com/a/61194625/10573560
How can I sort a Laravel Collection by multiple fields?
Imagine I have an "Exams" model, with a relation to "Patients", with date and score fields.
$exams = Exam::all();
$exams->load('Patient');
Now I want to sort this Collection by the patient name and then by the date of the exam.
$exams = $exams->sortBy('patient.name');
$exams = $exams->sortBy('date', 'desc');
This doesn't work, it ignores the first sortBy.
How can I achieve this?
Many thanks! :)
Try this: Hope it helps you.
$exams = Exam::with(
['patient' => function($query) {
$query->orderBy('name')
$query->orderBy('date','desc)
}
])
)->get();
You have to join patients.
Something like:
$exams = Exam::newQuery()
->join('patients', 'exams.patient_id', '=', 'patients.id')
->orderBy('patients.date', 'DESC')
->get()
;
I have the following code that works fine:
$products = Product::like($search)->whereIn('id', $request->input('product_ids'))->skip($offset)->take($limit)->get(array('products.*'))->sortBy(function($product) use ($sort_order) {
$number = (isset($sort_order[$product->id])) ? $sort_order[$product->id] : 0;
return $number;
});
This returns the items in ascending order, how do I specify whether I want sortby to return the products in ascending or descending order?
//$order contains either 'asc' or 'desc'
$products = Product::like($search)->whereIn('id', $request->input('product_ids'))->skip($offset)->take($limit)->get(array('products.*'))->sortBy(function($product) use ($sort_order, $direction) {
$number = (isset($sort_order[$product->id])) ? $sort_order[$product->id] : 0;
return ($direction == 'asc') ? $number : -$number;
});
I really don’t understand the query. There’s a lot going on there that really shouldn’t be. For example:
You’re not selecting data from any other table, so why are you specifying all rows from the products table in the get() method (->get(array('products.*')))?
Why are you applying the ordering function to the returned collection instead of just applying the order clause to the query?
With the above, you query could be simplified to something like:
$productIds = [1, 2, 3, 4];
$direction = 'asc'; // or desc
$products = Product::like($search)
->whereIn('id', $productIds)
->skip($offset)
->take($limit)
->orderBy('id', $direction)
->get();
Also, you don’t need to manually specify the offset and limit if you use the paginate() helper method.
Just use sortBy for ASC (how you used it now) and sortByDesc for DESC.
Of course I can use order_by with columns in my first table but not with columns on second table because results are partial.
If I use 'join' everything works perfect but I need to achieve this in eloquent. Am I doing something wrong?
This is an example:
//with join
$data = DB::table('odt')
->join('hdt', 'odt.id', '=', 'hdt.odt_id')
->order_by('hdt.servicio')
->get(array('odt.odt as odt','hdt.servicio as servicio'));
foreach($data as $v){
echo $v->odt.' - '.$v->servicio.'<br>';
}
echo '<br><br>';
//with eloquent
$data = Odt::get();
foreach($data as $odt){
foreach($odt->hdt()->order_by('servicio')->get() as $hdt){
echo $odt->odt.' - '.$hdt->servicio.'<br>';
}
}
In your model you will need to explicitly tell the relation to sort by that field.
So in your odt model add this:
public function hdt() {
return $this->has_many('hdt')->order_by('servicio', 'ASC');
}
This will allow the second table to be sorted when using this relation, and you wont need the order_by line in your Fluent join statement.
I would advise against including the order by in the relational method as codivist suggested. The method you had laid is functionally identical to codivist suggestion.
The difference between the two solutions is that in the first, you are ordering odt ( all results ) by hdt.servicio. In the second you are retrieving odt in it's natural order, then ordering each odt's contained hdt by servico.
The second solution is also much less efficient because you are making one query to pull all odt, then an additional query for each odt to pull it's hdts. Check the profiler. Considering your initial query and that you are only retrieving one column, would something like this work?
HDT::where( 'odt_id', '>', 0 )->order_by( 'servico' )->get('servico');
Now I see it was something simple! I have to do the query on the second table and get contents of the first table using the function odt() witch establish the relation "belongs_to"
//solution
$data = Hdt::order_by('servicio')->get();
foreach($data as $hdt){
echo $hdt->odt->odt.' - '.$hdt->servicio.'<br>';
}
The simple answer is:
$data = Odt::join('hdt', 'odt.id', '=', 'hdt.odt_id')
->order_by('hdt.servicio')
->get(array('odt.odt as odt','hdt.servicio as servicio'));
Anything you can do with Fluent you can also do with Eloquent. If your goal is to retrieve hdts with their odts tho, I would recommend the inverse query for improved readability:
$data = Hdt::join('odt', 'odt.id', '=', 'hdt.odt_id')
->order_by('hdt.servicio')
->get(array('hdt.servicio as servicio', 'odt.odt as odt'));
Both of these do exactly the same.
To explain why this works:
Whenever you call static methods like Posts::where(...), Eloquent will return a Fluent query for you, exactly the same as DB::table('posts')->where(...). This gives you flexibility to build whichever queries you like. Here's an example:
// Retrieves last 10 posts by Johnny within Laravel category
$posts = Posts::join('authors', 'authors.id', '=', 'posts.author_id')
->join('categories', 'categories.id', '=', 'posts.category_id')
->where('authors.username', '=', 'johnny')
->where('categories.name', '=', 'laravel')
->order_by('posts.created_at', 'DESC')
->take(10)
->get('posts.*');