Laravel how to get only one record per user - php

In my laravel-application, I want to display all users/candidates, which have taken an education. Now it might happen, that a user/candidate has taken more than one education, so in this case, just the latest education should be displayed.
I've come to this:
$users = User::whereHas('roles', function ($q) {
$q->where('slug', 'candidate');
}
)->whereHas('educations')
->join('user_educations', 'user_educations.user_id', '=', 'users.id')
->join('educations', 'user_educations.education_id', '=', 'educations.id')
->join('education_levels', 'user_educations.education_level_id', '=', 'education_levels.id')
->select('users.id', 'users.name', 'users.surname', 'users.status', 'users.city', 'users.zipcode', 'users.birthday', 'users.avatar', 'educations.title as education', 'education_levels.title as education_level')
->where('user_educations.user_id', '=', 'users.id') // HERE IT FAILS - returns null
->first();
return response(['success' => true, "users" => $users], 200);
when I leave out the where('user_educations.user_id', '=', 'users.id')-clause, and do get() instead of first(), I get all users/candidates with educations, and also sometimes the same user multiple times, depending on how many educations he has taken.
how can I fix this?

The distinct method allows you to force the query to return distinct results, you can use it like this;
$users = DB::table('users')->groupBy('user_id')->distinct()->get();
If you want to take just the latest record, you should use "orderBy" to order your records, than pick a record with something like this :
$users = DB::table('users')->groupBy('user_id')->orderBy('created_at','desc')->distinct()->get();
You can look here for more detailed information about query builders in Laravel

Related

How to add a where clause when using "with" on an Eloquent query in Laravel

I have a query built where I'm using "with" to include related models. However, I'm not sure how to filter those related models in a where clause.
return \App\Project::with("projectLeaders")->join('companies', 'company_id', '=', 'companies.id')
->join('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*');
Please note the with("projectLeaders") in the query. So, ProjectLeaders is a relation that brings objects of kind Employee, how can I filter in that query those "Employees" whose attribute "Lastname" is like "Smith" ?
You can implement where class both tables. Please check following code and comments.
return \App\Proyecto::with(["projectLeaders" => function($query){
$query->where() //if condition with inner table.
}])->join('empresas', 'id_empresa', '=', 'empresas.id')
->join('tipo_estado_proyecto', 'tipo_estado_proyecto.id', '=', 'proyectos.id_tipo_estado_proyecto')
->where() //if condition with main table column.
->select('empresas.*', 'tipo_estado_proyecto.nombre AS nombreEstadoProyecto', 'proyectos.*');
You can use Closure when accessing relation using with. Check below code for more details:
return \App\Project::with(["projectLeaders" => function($query){
$query->where('Lastname', 'Smith') //check lastname
}])->join('companies', 'company_id', '=', 'companies.id')
->join('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*');
You may use the where method on a query builder instance to add where clauses to the query. The most basic call to where requires three arguments. The first argument is the name of the column. The second argument is an operator, which can be any of the database's supported operators. Finally, the third argument is the value to evaluate against the column.
return \App\Project::with("projectLeaders")->join('companies', 'company_id', '=', 'companies.id')
->join('project_status', 'project_status.id', '=', 'projects.status_id')
->where('lastname','=','Smith')
->select('companies.*', 'project_status.name AS statusName', 'projects.*');
Don't forget to return results with a get();
The query you have written is correct. But after building the query you need to fetch the data from database.
METHOD ONE
So adding get() method to your query:
return App\Project::with('projectLeaders')
->leftJoin('companies', 'company_id', '=', 'companies.id')
->leftJoin('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*')
->get();
METHOD TWO (with pagination)
return App\Project::with('projectLeaders')
->leftJoin('companies', 'company_id', '=', 'companies.id')
->leftJoin('project_status', 'project_status.id', '=', 'projects.status_id')
->select('companies.*', 'project_status.name AS statusName', 'projects.*')
->paginate(3);

Laravel - add key/value to response if ids are the same

I have a contents table with a lot of contents created by different users… I’m trying to verify if a content is created by the user that is logged in and then add a new key value pair to the response, so if the content was created by user_id 1 and I’m user 1 then the response has a field like isOwn : 1 on the content object that is his own, but nothing if the content was created by someone else.
this is the criteria I have:
$query = $model->select('contents.*', 'status_types.name as status', 'content_types.name as content_type')
->join('status_types', 'status_types.id', '=', 'contents.status_type_id')
->join('content_types', 'content_types.id', '=', 'contents.content_type_id')
->with('platforms')
->with('classifications')
->withCount(['favorite' => function ($q) {
$q->where('user_id', '=', $this->request->user()->getIdentifier());
}])
->withCount('likes')
->inRandomOrder();
return $query;
I've tried to use when and whereExist but this return me only the ones created by the user, not if the condition is true.
Any ideas? thanks in advance.
You need to join on the model and make a where for the total query:
$query = $model->select('contents.*', 'status_types.name as status', 'content_types.name as content_type')
->join('status_types', 'status_types.id', '=', 'contents.status_type_id')
->join('content_types', 'content_types.id', '=', 'contents.content_type_id')
->join('favorites', 'favorites.contents_id', '=', 'contents.id') // or whatever the relation is
->with(['platforms', 'classifications'])
->withCount(['favorite'])
->withCount('likes')
->where('favorites.user_id', '=', $this->request->user()->getIdentifier())
->inRandomOrder();
return $query;

Laravel Query where All

I wondered how to make a Where All clause with Laravel
I'm trying to check if the episodes that a user saw are all the episodes of the series.
I'm using the WhereIn clause but i returns the results if i saw one episode of the serie.
$alleps get all the episodes of the serie
$seriessaw get all the episodes a user saw
Thank you for your answers !
$alleps = DB::table('episodes')
->select('episodes.id as ep_id')
->join('seasonsepisodes', 'episodes.id', '=', 'seasonsepisodes.episode_id')
->join('seriesseasons', 'seasonsepisodes.season_id', '=', 'seriesseasons.season_id')
->where('seriesseasons.series_id', '=', $id);
$seriesSaw = DB::table('usersepisodes')
->select('usersepisodes.episode_id as ep_id')
->where('usersepisodes.user_id', '=', Auth::user()->id)
->whereIn('usersepisodes.episode_id', $alleps)
->get();
I think you would need to set a having clause which would force records to only return if there's the same amount of records as there are amount of episodes.
$seriesSaw = DB::table('usersepisodes')
->select('usersepisodes.episode_id as ep_id')
->where('usersepisodes.user_id', '=', Auth::user()->id)
->whereIn('usersepisodes.episode_id', $alleps)
->having(\DB::raw('count(*)'), count($alleps))
->get();
You should note however that this would likely break if there's any possibility of having duplicates in the userepisodes table.
When you use WhereIn, you have to pass an array as the second parameter.
$alleps = DB::table('episodes')
->select('episodes.id as ep_id')
->join('seasonsepisodes', 'episodes.id', '=', 'seasonsepisodes.episode_id')
->join('seriesseasons', 'seasonsepisodes.season_id', '=', 'seriesseasons.season_id')
->where('seriesseasons.series_id', '=', $id)->get()->toArray();
$seriesSaw = DB::table('usersepisodes')
->select('usersepisodes.episode_id as ep_id')
->where('usersepisodes.user_id', '=', Auth::user()->id)
->whereIn('usersepisodes.episode_id', $alleps)
->get();

cant get the data I want from two different tables using Laravel

I have a table called instructor_class: user_id, class_id and I have another table classes: id, time, active.
I would like to show classes for a single user but only those classes that active is 0 or 1.
My current code looks like this:
return InstructorClass::with('classes.session')->where('user_id', '=', $userId)->get();
This code is displaying me everything, then I tried the following code:
$active = 1;
return InstructorClass::with(['classes' => function ($q) use ($active) {
$q->where('active', '=', $active); // '=' is optional
}])
->where('user_id', '=', $userId)
->get();
This again returns me same records, but of course the class property is null for each record, which at some point looks correct, but my point is if the 'active' field does not corresponds at the classes table do not show the record, seems like the where() stm within with() is optional..
I am kinda stuck here...
Would appreciate your help, opinions!
You can use ::has('classes') to only return the models that have related classes
return InstructorClass::has('classes')->with(['classes' => function ($q) use ($active) {
$q->where('active', $active);
}])
->where('user_id', '=', $userId)
->get();
Never thought it could be this simple:
return InstructorClass::with('classes.session')
->join('classes', 'classes.id', '=', 'instructor_class.class_id')
->where('classes.active', '=', 1)
->where('user_id', '=', $userId)
->get();

Eloquent - where has pivot users orWhere has none

I'm trying to write a function that will get all "buckets" that are assigned to the auth'd user and/or buckets that have NO USERS assigned.
Relations and such, work as they should. Unless I'm missing something?
How can I get all buckets user is assigned too - and also include buckets where no users (including the auth user) are assigned.
Buckets user is assigned to
Buckets where NO users have been assigned. i.e. pivot table contains no rows for bucket, etc.
My issue very likely stems from the orWhere query...
$buckets = Team::currentTeam()->buckets()->with('user')->whereHas('user', function($query) {
$query->where('user_id', Auth::user()->id)
->orWhere('user_id', function() {
$query->count();
}, '<', 0);
})->get();
Didn't tested this but I think this should work. You're looking to remove that orWhere query and add orHas('user', '=', 0).
$buckets = Team::currentTeam()->buckets()->with('user')->whereHas('user', function($query) {
$query->where('user_id', Auth::user()->id);
})->orHas('user', '=', 0)->get();
Another possible solution you might consider is using a left join.
Heads-up: this might not be accurate as I don't know your db schema.
Team::currentTeam()
->buckets()
->leftJoin('users', 'users.bucket_id', '=', 'buckets.id')
->where(function($query) {
$query->where('users.id', $user_id)
->orWhereNull('user.id');
});
Please also check this blog post
AND-OR-AND + brackets with Eloquent
https://laraveldaily.com/and-or-and-brackets-with-eloquent/

Categories