How to select only one Column with scope of eloquent model? - php

I got two tables. Both have a relationship to each other. I´m trying to query both to get the matching results. This results get checked if they also have an column which matches with a parameter value.
I´m trying it with a scope and it work. I only need one column from the second table and I´m trying to use it as column in my first table when I got my result.
So the code works and I got an result but I´m trying to filter to select only one column from the second table.
My code look like that.
My controller:
public function test()
{
$UID='LQuupgYvnuVzbEoguY4TF8bnHUU2';
$event=Events::withState($UID)->get();
echo $event;
}
My model scope function:
public function scopeWithState($query,$UID){
return $query->with(['EventLiked' => function($query) use($UID) {
$query
->where('EventLiked.UID', $UID)
;
}]);
}
My hasMany relationship function:
public function EventLiked()
{
return $this->hasMany(EventLiked::class,'EID','ID')->select('State','UID','EID');
}

I would go for specifying columns inside closure.
New scope:
public function scopeWithState($query,$UID){
return $query->with(['EventLiked' => function($query) use($UID) {
$query
->where('EventLiked.UID', $UID)
->select('State');
}]);
}
Calling scope:
$event=Events::withState($UID)->get();
You're not getting expected results because Laravel splits it into 2 queries:
First, for selecting events.
Then it plucks EID
Second, when it looks for EventLiked where matching ID's is found (from second step) and loads as relationships.
So you want to change select statement only in 2nd query. Not in a first one

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

Laravel 5 SQL Relations

I have some problem with a query in Laravel.
I want to create a filter query by column in server table but I don't know how to do this.
Need help to modify the following line:
$data = $video->files()->with('server')->get();
Model: server
public function files()
{
return $this->hasMany('App\Models\File', 'id', 'server_id');
}
Model: file
public function server()
{
return $this->belongsTo('App\Models\Server', 'server_id', 'id')->ordered();
}
My current query return this:
(but it returned all, I need return only FILE flitered by type = 6 which is server table) I don;t know how to do this. On screen below data about type server is on #relations array
Use WhereHas. Takes the relation name and a closure as a parameter, where you can define sub query like functionality with the relation.
$data = $video->files()->with('server')->whereHas('server', function ($query)
{
$query->where('type', '6');
})->get();

Laravel. Eloquent query

I got this query:
$users = DB::table('users')->whereExists(function($query)
{
$query->select(DB::raw(1))
->from('galleries')
->whereRaw('galleries.user_id = users.id');
})->get();
This query selects all users who have gallery. Problem is that I can't use eloquent releationships now. Whenever i try to loop like this:
#foreach ($user->gallery as $gallery)
{{$gallery->name}}
#endforeach
I get error:
Undefined property: stdClass::$gallery
It happens with all other tables. What am I doing wrong here? My realationships are defined and they work just fine, i got problems only in this query. Thanks.
EDIT
Since it's not eloquent query, could you show me example how to write query, into few tables with eloquent. For example, I need all users who have their status approved in example table
First, determine a relationship in the User class, like this:
class User {
// Determine relation to Example table
public function examples() {
return $this->hasMany('Example', 'user_id', 'id'); // second parameter is the foreign key
}
}
Then the query:
User::whereHas('examples', function( $query ) {
$query->where('status','approved');
})->get();

Laravel - Unnecessary columns still being loaded with select statement

I am wanting to limit a controller's function's result to only pass certain columns into the view.
It is necessary because it will be used within an API, and so I need the results to be as streamlined as possible.
I have done this successfully with the following function:
public function getIndex()
{
$alerts = Criteria::select('id', 'user_id', 'coordinate_id', 'alert_name')
->with(['coordinate' => function($q){
$q->select('name', 'id');
}])
->get();
}
So it only returns id, user_id and coordinate_id from the criteria table.
However on the function below, I am using a has query (to access a relationship), and thus, using with afterwards to limit the columns, but it's still returning all:
public function getMatches()
{
$matches = Criteria::select('id')
->has('alerts')
->with(['alerts' => function ($q){
$q->select('id', 'headline', 'price_value', 'price_type');
}])
->with('alerts.user.companies')
->get();
}
But, for example, it's still returning the description column, which is in the alert's table. The with query proceeding the has query clearly isn't working (but it's presenting no errors).
Also, the ->with('alerts.user.companies') query, is returning everything within the user's table, which is also unnecessary. How can I return just the companies table data, that's related to the user, who's related to the alert?
Your help would be greatly appreciated.
Depending what you want to achieve, you could use $hidden property to hide columns you don't want to return as json or arrays.
In your Alert model you could do:
protected $hidden = ['description'];
And this way description field won't be returned.
If it's not the way for you (sometimes you want to return description) you could create extra relationships where you limit fields from database.
You could for example create the following relationship:
public function alertsSimple() {
return $this->hasMany('Alert')->select('id', 'headline', 'price_value', 'price_type', 'criteria_id');
}
Also maybe in your select the problem is that you don't use foreign key at all. You could also try with:
$q->select('id', 'headline', 'price_value', 'price_type','criteria_id');
instead of
$q->select('id', 'headline', 'price_value', 'price_type');

How to order by pivot table data in Laravel's Eloquent ORM

In my Database, I have:
tops Table
posts Table
tops_has_posts Table.
When I retrieve a top on my tops table I also retrieve the posts in relation with the top.
But what if I want to retrieve these posts in a certain order ?
So I add a range field in my pivot table tops_has_posts and I my trying to order by the result using Eloquent but it doesn't work.
I try this :
$top->articles()->whereHas('articles', function($q) {
$q->orderBy('range', 'ASC');
})->get()->toArray();
And this :
$top->articles()->orderBy('range', 'ASC')->get()->toArray();
Both were desperate attempts.
Thank you in advance.
There are 2 ways - one with specifying the table.field, other using Eloquent alias pivot_field if you use withPivot('field'):
// if you use withPivot
public function articles()
{
return $this->belongsToMany('Article', 'tops_has_posts')->withPivot('range');
}
// then: (with not whereHas)
$top = Top::with(['articles' => function ($q) {
$q->orderBy('pivot_range', 'asc');
}])->first(); // or get() or whatever
This will work, because Eloquent aliases all fields provided in withPivot as pivot_field_name.
Now, generic solution:
$top = Top::with(['articles' => function ($q) {
$q->orderBy('tops_has_posts.range', 'asc');
}])->first(); // or get() or whatever
// or:
$top = Top::first();
$articles = $top->articles()->orderBy('tops_has_posts.range', 'asc')->get();
This will order the related query.
Note: Don't make your life hard with naming things this way. posts are not necessarily articles, I would use either one or the other name, unless there is really need for this.
For Laravel 8.17.2+ you can use ::orderByPivot().
https://github.com/laravel/framework/releases/tag/v8.17.2
In Laravel 5.6+ (not sure about older versions) it's convenient to use this:
public function articles()
{
return $this->belongsToMany('Article', 'tops_has_posts')->withPivot('range')->orderBy('tops_has_posts.range');
}
In this case, whenever you will call articles, they will be sorted automaticaly by range property.
In Laravel 5.4 I have the following relation that works fine in Set model which belongsToMany of Job model:
public function jobs()
{
return $this->belongsToMany(Job::class, 'eqtype_jobs')
->withPivot(['created_at','updated_at','id'])
->orderBy('pivot_created_at','desc');
}
The above relation returns all jobs that the specified Set has been joined ordered by the pivot table's (eqtype_jobs) field created_at DESC.
The SQL printout of $set->jobs()->paginate(20) Looks like the following:
select
`jobs`.*, `eqtype_jobs`.`set_id` as `pivot_set_id`,
`eqtype_jobs`.`job_id` as `pivot_job_id`,
`eqtype_jobs`.`created_at` as `pivot_created_at`,
`eqtype_jobs`.`updated_at` as `pivot_updated_at`,
`eqtype_jobs`.`id` as `pivot_id`
from `jobs`
inner join `eqtype_jobs` on `jobs`.`id` = `eqtype_jobs`.`job_id`
where `eqtype_jobs`.`set_id` = 56
order by `pivot_created_at` desc
limit 20
offset 0
in your blade try this:
$top->articles()->orderBy('pivot_range','asc')->get();
If you print out the SQL query of belongsToMany relationship, you will find that the column names of pivot tables are using the pivot_ prefix as a new alias.
For example, created_at, updated_at in pivot table have got pivot_created_at, pivot_updated_at aliases. So the orderBy method should use these aliases instead.
Here is an example of how you can do that.
class User {
...
public function posts(): BelongsToMany {
return $this->belongsToMany(
Post::class,
'post_user',
'user_id',
'post_id')
->withTimestamps()
->latest('pivot_created_at');
}
...
}
You can use orderBy instead of using latest method if you prefer. In the above example, post_user is pivot table, and you can see that the column name for ordering is now pivot_created_at or pivot_updated_at.
you can use this:
public function keywords() {
return $this->morphToMany(\App\Models\Keyword::class, "keywordable")->withPivot('order');
}
public function getKeywordOrderAttribute() {
return $this->keywords()->first()->pivot->order;
}
and append keyword attribiute to model after geting and use sortby
$courses->get()->append('keyword_order')->sortBy('keyword_order');

Categories