Good morning,
I have this function to order my products by 'most expensive' and 'most cheap', and It's working fine, but the problem is, I have some products without image and I want them be moved to the last page, when I do the follow:
->addOrderBy('u.status','desc')
->addOrderBy('u.imagem', 'DESC')
->addOrderBy($order,$for)
->getQuery()
He move the product without images to the last page, But doesnt work my OrderBy to order by Most Expensive and Cheap.
When `
->addOrderBy('u.status','desc')
->addOrderBy($order,$for)
->addOrderBy('u.imagem', 'DESC')
->getQuery()
Works fine but images continue random.
Since the u.imagem field is null when the product has no image, you could:
1.- If you want to inhibit the products without images from the results:
Add a where clause for u.imagem IS NOT NULL and you'll only be returned results that have images.
2.- If all you want/need is to keep the products with no image in the listing but at the end, you can:
->addOrderBy('u.status','desc')
->addOrderBy($order,$for)
->addOrderBy('u.imagem IS NULL', 'ASC')
->getQuery()
The above works because IS NULL returns a 0 when false and a 1 when true. By sorting those 1s and 0s in ascending order, you'll get all the ones that don't satisfy IS NULL (i.e., the ones that actually have images) first, then the others
Related
I have the following relations
Transaction Table is the parent table for ETransaction and ATransaction and belongs to transactions table
$transactionA= Transaction::with('tAccount')->has('tAccount')->get();
$transactionE= Transaction::with('tExchange')->has('tExchange')->get();
$collection = collect([$transactionE,$transactionA]);
$sorted = $collection->sortBy('created_at') do not work for me
The main problem you encounter isn't necessarily about sorting, but about building up the initial collection.
Right now, you make two collections, transactionA and transactionE. You then initialize a third collection collection that contains both transactionA and transactionE.
You can think of this as transactionA being a box of records, and transactionE being another box of records. What you want is one big box of records, but the current code puts both boxes in another, bigger box. When sorting the bigger box, all you sort is the order in which the smaller boxes end up in the bigger box.
What you presumably want instead, is to merge the contents of both boxes and sort the ensemble. You can do so by merging the two collections:
$collection = $transactionA->merge($transactionE);
I'm not sure why you even need separate queries. Stratadox's answer shows how to query, merge and sort, but you can do that in a single query using Eloquent:
$collection = Transaction::with(["tAccount", "tExchange"])
->has("tAccount")
->orHas("tExchange")
->orderBy("created_at")
->get();
In a single query, this will look for all Transaction records that have either a tAccount or tExchange record associated, sort it by the created_at timestamp and return it in a single call. Pushing the logic to the Collection class can be inefficient, so let the database handle it when possible.
I am trying to do get all the latest items and sort by id descending (i.e. get all items that were just added with a limit and offset).
So I did this:
$products = Product::all()
->slice($request->get('offset'))
->take($request->get('limit'))
->sortByDesc('id')
->toBase();
However it seems when I have more that that limit, then I dont have the right order. It gets me say 10 products but not sorted corrected. Any idea how to do this with Eloquent ORM?
You are probably intending to have the database handle the offset and skipping and ordering instead of pulling all the possible records then taking only what you want, then sorting them ... if you were going to do it your way you would need to sort before you skip and take, by the way.
Using the database to the the filtering and ordering:
$products = Product::skip($request->input('offset'))
->take($request->input('limit'))
->orderBy('id', 'desc')
->get();
I think the issue is you're using ::all() first, which returns all Product instances in a Collection, then using collection methods. Since these methods act in order of usage, you're slicing and offsetting before sorting, so you'll get the same products each time. Use proper Builder syntax to handle this properly and more efficiently:
$products = Product::offset($request->input("offset"))
->limit($request->input("limit"))
->orderBy("id", "DESC")
->get();
Because this is a Builder instance, the query will be compiled and executed according to your Database's grammar logic, and in a single query. There's nothing wrong in using Collection logic, you'd simply have to use the correct order of methods (sortByDesc() first, then slice(), then take()), but this is incredibly inefficient as you have to handle every Product in your database.
I am doing a Left Join where I would like to get the data from a table and the count of the appearance of the ID of another table, I have the table:
'tab_areas_atuacoes'
which is a specialty of a professional, and I have the table
'tab_medicos_as_area_atuacao'
which is the table that has all the specialities of each professional, where each professional can have more than one speciality.
I want to get the data from 'tab_areas_atuacoes' and I want to get the amount of specialties that each professional has, but I'm not getting results. Could someone give me some idea? So far I have this:
DB::table('tab_areas_atuacoes')
->whereNull('deleted_at')
->leftJoin('tab_medicos_as_areas_de_atuacao', function($query){
$query->on('tab_medicos_as_areas_de_atuacao.rel_area_atuacao_id', 'tab_areas_atuacoes.esp_id');
$query->selectRaw('tab_medicos_as_areas_de_atuacao.*, count(tab_medicos_as_areas_de_atuacao.rel_area_atuacao_id) as total');
})->select('esp_id', 'esp_data', 'esp_titulo', 'esp_status', 'deleted_at')->groupBy('tab_areas_atuacoes.esp_id');
Thank you in advance for your help!
I'm afraid I don't really understand the structure so there was a bit of guesswork involved here. You had a select within your join, I'm not sure if you were actually trying to add all those columns to the result set or not. You can add all the columns you need to the initial select or add others later with an addSelect() call.
DB::table('tab_areas_atuacoes')
->select(
'esp_id',
'esp_data',
'esp_titulo',
'esp_status',
'deleted_at',
DB::raw(
'COUNT(tab_medicos_as_areas_de_atuacao.rel_area_atuacao_id) AS total'
)
)->leftJoin(
'tab_medicos_as_areas_de_atuacao',
'tab_medicos_as_areas_de_atuacao.rel_area_atuacao_id',
'=',
'tab_areas_atuacoes.esp_id'
)->whereNull('deleted_at')
->groupBy('tab_areas_atuacoes.esp_id'));
I am struggling with a pretty difficult thing and hope you can help me out.
Right now I've got the following:
$ads = Ad::where('status', 1)
->whereIn('ad_type', [1, 2, 3])
->where('expire_at', '>', date('Y-m-d H:i:s'))
->where('special_ad', 'standard_ad')
->orderByRaw(DB::raw("FIELD(ad_type,2,3,1)"));
Info:
This is working because it is an Eloquent Collection and I can Paginate this (needed for my Infinite Scroll)
But now I want to shuffle the ad_types in itself, meaning:
ad_type 1 could have, let's say, 30 entries. They will all be returned in the usual order. I want to shuffle those 30 every time I run this query.
I thought about doing ->toArray(); but then again, no pagination (Pagination only works on Eloquent Queries right?)
Then I thought, hey, let's merge this.
But as soon as I did that, the returned collection is no longer an Eloquent Collection but a Support Collection (right? I am not 100% sure it is a Support Collection) thus the Pagination does not work anymore.
I read upon many posts as how to solve this problem, and figured out one solution may be to "create my own paginator instance"
But heck, I am not that good yet. I do really not know, even after studying the laravel documentation, how to create my own paginator.
Important Infos you might need:
Using Laravel 5.2
$ads are dynamical, meaning depending on the case, the requests sent with Ajax, the query might differ at a later point (something might get included).
Thank you very much for your time reading this and hopefully, you can help me and future readers by solving this particular problem.
Greetings, and a great weekend to all of you.
Firstly just to note:
Pagination does not only work for database queries. You can manually paginate using LengthAwarePaginator but manually is the keyword here. The query builder (not Eloquent) can do it automatically for you using paginate.
You can "shuffle" the results by doing something like
$ads = Ad::where('status', 1)
->whereIn('ad_type', [1, 2, 3])
->where('expire_at', '>', date('Y-m-d H:i:s'))
->where('special_ad', 'standard_ad')
->orderByRaw("FIELD(ad_type,2,3,1)")
->orderByRaw("RAND()");
This will order by the ad_type field first and order by a random number (different for every row) as a secondary sort.
$notif = DB::table('notifications')->orderBy('updated_at', 'desc')->get();
Above code is to get the values in descending order according to the default column updated_at in laravel 5. Although that will display the values ascending order. I want to display the most recently updated one at first.How to correct that?
Looks like you are viewing the results from phpmyadmin or something similar. The code
$notif = DB::table('notifications')->orderBy('updated_at', 'desc')->get();
will give you results in your web application.
It'll not store the records in descending order in the database as you are expecting.
Your statement $notif = DB::table('notifications')->orderBy('updated_at', 'desc')->get(); definately gives you the right sorting. As #linuxartisan already mentioned: are you sure your tool you are using for showing the database uses the right sort direction? It seems 11, 12 in your first column is the the id and the sort order is using id ascending