Order data by pivot table when try to use With - php

I have tables Polfzms <- Genes
Polfzm model have next relation
public function gene()
{
return $this->belongsTo('App\Gene');
}
I need get all data from Polfzms table with data from Genes table and order it by name from pivot table (Genes). I try next
$data = Polfzm::with([
'gene' => function ($query) {
$query->orderBy('name', 'asc');
},
])->get();
but it not order data by name. How can I do it?

You could try to set this in the relationship definition:
Polfzm.php
public function gene()
{
return $this->belongsTo('App\Gene')->orderBy('name', 'asc');
}
Then in your controller:
$data = Polfzm::with('gene')->get();

If I understand correctly, you could use a collection sortBy helper for this one.
An example could be:
$data = Polfzm::with('gene')
->get()
->sortBy(function ($polfzm) {
return $polfzm->gene->name;
});

Related

Datatables: how to preserve id when sorting through a relation from another table (yajra, laravel)

I'm using datatables from yajra datatables and I have a problem.
I have a datatable where I obtain certain columns from other tables, for example the column "customer" is obtained through a relation from another table
But when I press the sort by customer button, the IDs change to the ID of the table where the relation belongs
This generates errors in the buttons that I have on the right since these IDs do not exist in the "meos" table, only in the "locations" table that is in the relation
How can I make it sort while keeping the same ID it had?
I want to always keep as order criteria the ID of the table I am with, which is the "meos" table belonging to the "meo" class
This is my query
public function query()
{
$languageId = Auth::user()->language_id;
return Meo::with(['businessType' => function ($query) use ($languageId) {
$query->with(['businessTypeDescriptions' => function ($subQuery) use ($languageId) {
$subQuery->where('language_id', '=', $languageId);
}]);
}])->with('location');
}
this is my function getcolumns
protected function getColumns()
{
return [
Column::make('id')->addClass('text-center')->title(__('digestReport.columns.id')),
Column::make('location.location_name')->addClass('text-center')->title(__('digestReport.columns.customer')),
Column::make('businessType')->addClass('text-center')->title(__('digestReport.columns.business_type'))->searchable(false),
Column::computed('action')->exportable(false)->printable(false)->width(160)->addClass('text-center')->title(__('digestReport.columns.actions')),
];
}
please, I need help.
Thanks :)
Try below code. Add ->select() statement
public function query()
{
$languageId = Auth::user()->language_id;
return Meo::with(['businessType' => function ($query) use ($languageId) {
$query->with(['businessTypeDescriptions' => function ($subQuery) use ($languageId) {
$subQuery->where('language_id', '=', $languageId);
}]);
}])->with('location')->select('meo-table.*');
}
Replace meo-table with your database table for Meo::class

Sort related table inside of the loop to build js array from php

Quick question, I have Model that related to different model (one to many).
I'm building method that should return js array with related table included to array.
But I need to sort a bit warrant_grants, I need to return $warrant_grants->where('status', active). So My ->where() doesn't work this way:
public function warrants($company_id){
$company = auth()->user()->companies()->findOrFail($company_id);
$warrants = $company->warrants;
foreach($warrants as $warrant) {
//this doesn't work
$warrant->warrantGrants->where('status', 'active');
}
$warrants = $warrants->toArray();
return array_splice($warrants, 0);
}
Relationship:
public function warrantGrants()
{
return $this->hasMany(WarrantGrant::class);
}
Need this little help, bc it returns me data with any status, I need only 'active'
Try this
$company = App\Company::whereHas('warrants.warrantGrants', function ($query) {
$query->where('status', '=', 'active');
})->get();

How OrderBy afterwards HasMany and BelongsTo Relationships

I created a relationship between the "Review, Games and Info" tables, unfortunately, though, the main table is Games, and he orders me all for Games, While I would like to order the ID of "review" table.
Models: Review
public function games()
{
return $this->hasMany('App\Models\Giochi', 'id_gioco', 'id');
}
Models: Giochi
public function review()
{
return $this->belongsTo('App\Models\Review', 'id', 'id_gioco');
}
public function infogiochi()
{
return $this->belongsTo('App\Models\InfoGiochi', 'id', 'id_gioco');
}
Models: InfoGiochi
public function games()
{
return $this->hasMany('App\Models\Giochi', 'id', 'id_gioco');
}
Controller:
$review = Giochi::with('Review','InfoGiochi')->orderBy('id','DESC')->get();
Here is a screenshot of my json:
How do I order content for review table IDs?
You have 2 options. You use a join and order in the sql statement or you order it after retrieving the results in the collection.
Using Join
Giochi::select('giocos.*')
->with('Review','InfoGiochi')
->leftJoin('reviews', 'reviews.id', '=', 'giocos.id_gioco')
->orderBy('reviews.id','DESC')
->get();
Sorting Collection
Giochi::with('Review','InfoGiochi')
->get()
->sortByDesc(function($giochi) {
return $giochi->review->id;
});
This would be the shortest version to sort on the collection:
Giochi::with('review')
->get()
->sortByDesc('review.id');
You can modify your relationship query when you fire it:
Giochi::with([
'Review' => function ($query) { return $query->orderBy('id','DESC'); },
'InfoGiochi'
])->orderBy('id','DESC');
You can try with a raw query or you can use ->orderBy() directly on review function.

Laravel With and wherePivot

I'm trying to extract all companies and contacts with pivot.main_contact = 1.
Tables:
Company: id, name
Company_contacts: id, company_id, contact_id, main_contact
Contacts: id, name
Model:
class Company extends Model
{
public function mainContact()
{
return $this->belongsToMany('App\Contact', 'company_contacts')
->wherePivot('main_contact', '=', 1);
}
}
Controller:
$query = Company::with('mainContact')->get();
This returns companies + ALL contacts for the companies and NOT ONLY the ones with main_contact = 1.
First, for reasons I'm unsure of, you need to add withPivot('main_contact'); to your relation. This will return main_contact in your collection under pivot
class Company extends Model
{
public function mainContact()
{
return $this->belongsToMany('App\Contact', 'company_contacts')
->withPivot('main_contact');
}
}
The second thing you need to do is use withPivot() while constraint eager loading like so:
$companies = Company::with(['mainContact'=> function($query){
$query->wherePivot('main_contact', 1);
}])->get();
I've checked it, it works.
Just to go a bit above and beyond. Sometimes you'll want to query a pivot table without knowing the value. You can do so by:
$companies = Company::with(['mainContact'=> function($query) use ($contact){
$query->wherePivot('main_contact', $contact);
}])->get();
Try to add withPivot():
return $this->belongsToMany('App\Contact', 'company_contacts')
->withPivot('main_contact')
->wherePivot('main_contact', '=', 1);
Company::with('mainContact')->get(); returns all compaines and all contacts. You should be doing $company->mainContacts()->get(); instead.
$companies=Company::all();
foreach($companies as $company)
{
print_r($company->mainContact()->get());
}
die;

Laravel Eloquent: How to order results of related models?

I have a model called School and it has many Students .
Here is the code in my model:
public function students()
{
return $this->hasMany('Student');
}
I am getting all the students with this code in my controller:
$school = School::find($schoolId);
and in the view:
#foreach ($school->students as $student)
Now I want to order the Students by some field in the students table. How can I do that?
You have a few ways of achieving this:
// when eager loading
$school = School::with(['students' => function ($q) {
$q->orderBy('whateverField', 'asc/desc');
}])->find($schoolId);
// when lazy loading
$school = School::find($schoolId);
$school->load(['students' => function ($q) {
$q->orderBy('whateverField', 'asc/desc');
}]);
// or on the collection
$school = School::find($schoolId);
// asc
$school->students->sortBy('whateverProperty');
// desc
$school->students->sortByDesc('whateverProperty');
// or querying students directly
$students = Student::whereHas('school', function ($q) use ($schoolId) {
$q->where('id', $schoolId);
})->orderBy('whateverField')->get();
you can add orderBy to your relation, so the only thing you need to change is
public function students()
{
return $this->hasMany('Student');
}
to
public function students()
{
return $this->hasMany('Student')->orderBy('id', 'desc');
}
To answer the original question, the students dynamic property can also be accessed as a relationship method.
So you have this to fetch all students:
$students = $school->students;
Now as a relationship method, this is equivalent:
$students = $school->students()->get();
Given this, you can now add in some ordering:
$students = $school->students()->orderBy('students.last_name')->get();
Since eloquent will be performing a join, make sure to include the table name when referencing the column to order by.
You can also add this to your students method if you want to set a default order that $school->students will always return. Check out the documentation for hasMany() to see how this works.
For Many to one relation I found one answer on:
https://laracasts.com/discuss/channels/eloquent/order-by-on-relationship
$order = 'desc';
$users = User::join('roles', 'users.role_id', '=', 'roles.id')
->orderBy('roles.label', $order)
->select('users.*')
->paginate(10);
this can save day... of anyone
You can use this like this:
$students = $school->students()->orderBy('id', 'desc');
You can also use
$students = $school->students()->orderBy('id', 'desc')->paginate(10);

Categories