How to use a where query inside a laravel relationship? - php

Hello i have a CommentRetours table which connects the retours to the comments.
The DB:
I need to display all comments for a user and return that to the view.
I now have this query:
$comments = CommentRetours::with(['comments' => function($q) {
$q->where('user_id',Auth()->user()->id);
}])->get();
This return NULL..
The user_id is inside the comments table.
As constructure example i will add this:
What am i doing wrong?

The question is quite old but the solution adopted by OP being less than ideal, here is what he probably should have done:
$comments = CommentRetours::whereHas(['comments' => function($q) {
$q->where('user_id', Auth::id());
}])->with('comments')->get();
whereHas checks if the CommentRetours have some comments that match the condition.
I also replaced Auth()->user()->id by Auth::id().

I fixed it by adding user_id to the CommentRetours table, now I wont have to query inside the other relationship.
I can just see user_id directly inside the table.

Related

Laravel eloquent update column using relationship column

How can achieve this query?
Sale::with(['catalog'])
->whereIn('id', $ids)
->update(['price' => DB::raw('catalog.price')]);
This is not working, it shows undefined table... I tried to put the name of the table but it's the same.
On the internet I always found the easy query:
Sale::with(['catalog'])
->whereIn('id', $ids)
->update(['price' => 5]);
Okay! When I want to update all rows with the same value is easy, in addition is easy when you want to update with a column of the same table like:
Sale::with(['catalog'])
->whereIn('id', $ids)
->update(['price' => DB::raw('price_alternative')]);
But how about using a column of another table with a relationship? I haven't found the solution.
I know this can be solved using entire raw query, but I wanted to know if it can be achieved by the eloquent way
You probably need to join in the catalog table on your querybuilder. This is different than using with(). Something along the lines of
Sale::whereIn('id', $ids)
->join('catalog', 'sales.catalog_id', '=', 'catalog.id')
->update(['price' => DB::raw('catalog.price')]);
This is not better than answer of #Qirel, but it is Eloquent way, i like this because that's more clearly.
$Sales = Sale::whereIn('sales.id', $ids)
->with('Cat')->get();
$Sales->map(function($q){
$q->price = $q->Cat->price;
$q->save();
});
Assume you have this relation code in Sale model:
public function Cat()
{
return $this->hasOne(CatModel::class, 'id', 'catalog_id');
}

Eloquent limit relationship fields

I have the following relationships:
TheEpisodeJob hasOne TheEpisode
TheEpisodeJob hasMany TheJobs
I am successfuly retrieving all TheEpisodesJobs and TheSeriesEpisodes with all the fields in database (including sensitive information) using this command:
$jobs = TheEpisodeJob::with('TheEpisode')->get();
I would like to limit TheEpisode fields shown only for this case (public $hidden will not work)
EDIT
Let's say I need only title and description field from TheEpisode.
How can I achieve that?
As #Buglinjo pointed out you can scope the relationship when eager loading, however, if you're going to be doing this to only select specific columns you must included the related column in the select so that Eloquent knows which Model to attach the related data to.
This should give you what you want:
$jobs = TheEpisodeJob::with(['TheEpisode' => function ($query) {
$query->select('jobID', 'title', 'description');
}])->get();
Furthermore, if you then wanted to to get rid of the jobID as well you could do something like:
$jobs->transform(function ($job) {
$job->TheEpisode->transform(function ($item) {
unset($item->jobID);
return $item;
});
return $job;
});
Hope this helps!
As far as I understood you, you want to limit the results according to some more parameters. If I am right, you should add more queries, like:
->where, ->orwhere, ->select, ->whereNull
Here is the link for more queries. Hope it will help )
I saw an update, so then you need
->pluck('title', 'description');
for more information, go to the link above
You should do like this:
$jobs = TheEpisodeJob::with(['TheEpisode' => function($q){
$q->get(['title', 'description']);
//or
$q->pluck('title', 'description');
}])->get();
Note: pluck is getting as array not as Eloquent Object.

Laravel OrderBy Nested Collection

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

Laravel 5.1 select field in with function

Can I select value from relationships with function "with" ?
So make something like this:
$test = User::where('id',1)->with(['user_detail' => function($query){
$query->select("detail_1");
}])->get();
Yes I know that I can put select in relation "user_detail" but can I select in with function?
You can select within with as you made the example given below:
$test = User::where('id',1)->with(['user_detail' => function($query){
$query->select("detail_1");
}])->get();
But it won't not work (as you commented in other answer) because you've only selected a single property but the foreign key is not available in your select statement. So, make sure that, you also select the related foreign key as well and then it'll work.
In your case, I believe that, you've to also select the user_id in your select for example:
$test = User::where('id',1)->with(['user_detail' => function($query){
$query->select(
'user_id', // This is required if this key is the foreign key
'detail_1'
);
}])->get();
So, without the foreign key that makes the relation, Eloquent won't be able to load the related models and that's why you get null in your result as you mentioned in other comment.
Yes, you can use select() inside with(). Just pass an array of columns:
$query->select(['detail_1', 'detail_2']);
Alternatively, you can create another relation and add select() to it:
public function userDatails()
{
return $this->hasMany('App\UserDetail')->select(['detail_1', 'detail_2']);
}
$result = Staff::where('live_status',2)
->with('position')->with('department')->with('gender')
->with(['partner' => function($query){
$query->where('alive',0);
}]);

Match array of ids from pivot table

Scenario
I have 3 main tables Employees,Jobs,Skills. Employees and Jobs has many-to-many relationship with Skills table.
So, an employee can have skills 1,2,3,5. A job may requires skills 1,3,5.
Now my question is how can I match the id's in an eloquent query. Like, if I want to search all the employees for a job requiring skills 1,3,5, it should search all the employees having all those skills(1,3,5)
You said you have an array of IDs, so use multiple whereHas():
$employees = Employee::JobLocations($jobZipId);
foreach ($skillIds as $id) {
$skilledEmployees = $emloyees->whereHas('skills', function ($q) use ($id) {
$q->where('id', $id);
});
}
$skilledEmployees = $skilledEmployees->get();
You can do it like, I am taking $job as already a defined object.
Employee::whereHas('skills', function($q) use($job) {
$q->whereIn('id', $job->skills->lists('id')->toArray());
})->get();
Update
In case of Laravel 5.3 and up, the method lists won't work (as its is removed) so you can also use pluck method instead of lists.
Hope this helps you to solve your problem.

Categories