Laravel show only record belong to user with relationships - php

I have builded a system in larvel and vue js, so i have some users who can have access on this system. Now i need for each user they to see only data belongs to his team where hi is on this team. I have some workers, teams, and jobs. When a worker is created, a user is also created in the users table. the user that is created takes a field called worker_id that corresponds to the id of the worker that is created. Now this worker is in a team, and several jobs have been assigned to this team. I want that when this user who has the same worker_id with worker->id logs in, he can only see the jobs assigned to his team.
jobcontroller function to show jobs
$jobs = Job::with(['teams', 'clients'])
->whereHas('teams', function ($q) {
return $q->where('id', auth()->user()->worker_id); //i know there is wrong, iam just trying
})
->orderBy('id', 'DESC')->paginate($paginate);
return JobResource::collection($jobs);
jobrelationships
public function teams()
{
return $this->belongsToMany(Team::class);
}
public function clients()
{
return $this->belongsToMany(Client::class);
}
teamrelationship
public function jobs()
{
return $this->belongsToMany(Job::class);
}
workerrelationsip
public function teams()
{
return $this->hasOne(Team::class);
}

In your example you are attempting to query for teams by using the worker ID, rather than querying for teams using the worker's team ID.
$workerId = auth()->user()->id;
$jobs = Job::with('teams.workers')
->whereHas('teams.workers', function ($q) { return $q->where('id', $workerId); })
->orderBy('id', 'DESC')
->paginate(10);
return JobResource::collection($jobs);

Related

laravel query relationship to check if data exists

I have a set up like this,
QUIZ MODEL
public function scores()
{
return $this->hasMany('App\Score');
}
SCORE MODEL
public function quiz()
{
return $this->belongsTo('App\Quiz');
}
public function user()
{
return $this->belongsTo('App\User');
}
USER MODEL
public function scores()
{
return $this->hasMany('App\Score');
}
Some background, a quiz should only be playable by a user if that user does not already have a score for said quiz, what I am wanting to do is that if a user has a relationship with a quiz via having a score I want to stop that quiz being return in the query, here is my attempt,
$quiz = Quiz::with('questions.answers')
->has('scores.user', 2)
->whereDate('date_playable', '=', $date)
->first();
However this returns no quizes regardless of whether the user has a score for it or not. Can anyone enlighten me on how to only return quizes that a user does not currently have a score for?
You are currently searching for a quiz that does not have more than 2 scores for any user.
What you need is whereDoesntHave instead:
$quiz = Quiz::with('questions.answers')
->whereDoesntHave('scores', function ($query) use ($user) {
$query->where('user_id', $user->id);
})
->whereDate('date_playable', '=', $date)
->first();
Where $user is the App\User instance that you are querying for.
There could be multiple approaches to achieve that outcome. I am thinking about creating a many to many relationship between Quizzes and Users, taking scores as the middle table.
User
{
public function quizzes()
{
return $this->belongsToMany(Quiz::class, 'scores');
}
}
Then to get the desired quiz:
$quiz = Quiz::with('questions.answers')
->whereKeyNot($user->quizzes()->pluck('id')->all())
->whereDate('date_playable', '=', $date)
->first();

Laravel 5.5 three table join

Edit: I am using API routes, so i have no views and such
I have a database like this
User:
id
name
card:
id
card_number
user_id
swipe:
id
time
card_number
the relationships go as followed user has one card one card has many swipe
the joins would be as such
user.id = card.user_id
card.card_number = swipe.card_number
In Larvel i have 3 models.
user
card
swipe
user Model
class user extends Model
{
public function card()
{
return $this->hasOne('App\card','user_id','id');
}
}
in a controller if i do
$model = user::with('card')->get();
i get the card data joined with the user data as expected.
class card extends Model
{
public function person()
{
return $this->belongsTo('App\user');
}
public function swipe(){
return $this->hasMany('App\swipe','card_number','card_number');
}
}
if i now do
$model = user::with('card.swipe')->get();
which i would expect to return all the users with their cards, and swipes associated to that card.
However what i get is
500 internal server error
What am i doing wrong here?
For Example you can use like this.
$shares = DB::table('shares')
->join('users', 'users.id', '=', 'shares.user_id')
->join('follows', 'follows.user_id', '=', 'users.id')
->where('follows.follower_id', '=', 3)
->get();
You cant use like this,
user::with('card.swipe')->get();
Use Has many Through
https://laravel.com/docs/5.5/eloquent-relationships#has-many-through
user - countries (in docs)
card - users (in docs)
swipe - posts (in docs)
$country->posts;
$user->swipe;
I don't know if this is right solution, but you can try:
public function swipe(){
return $this->hasMany('App\swipe')->where('card_number','card_number');
}
You should be able to extract your data in your controller like this:
return user::with(['card' => function($query) {
$query->with('swipe');
}])->get();
Make sure your swipe model "belongsTo('App\card')".

Laravel querying multiple related models

For example: I have these models in my application.
User, Profile, Interest.
I linked the users table with the profiles table by adding the user_id column in the profiles table. And I linked profiles and interests by using a pivot table (interest_profile), Which is (as obvious) will have two columns (profile_id, interest_id).
However, I want to query the users who are associated with a profile, too see who is associated with a particular interest, In other words: "select all users who are having (in their profiles) that particular interest".
I know that I can do this with raw SQL by joining the four tables and then use (where clause).. But I want to do it the Laravel way.
Thanks in advance.
First make sure you have your relationships setup correctly on your models like:
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function interests()
{
return $this->belongsToMany(Interest::class, 'interest_profile');
}
}
class Interest extends Model
{
public function profiles()
{
return $this->belongsToMany(Profile::class, 'interest_profile');
}
}
Then you can use whereHas() to constrain a query by a related model and dot notation for nested relations. So your query would be:
User::whereHas('profile.interests', function($query) use ($interestName) {
return $query->where('name', $interestName);
})->get();
That would just return a collection of users. If you wanted to return their profiles and interests as well you would use with():
User::whereHas('profile.interests', function($query) use ($interestName) {
return $query->where('name', $interestName);
})
->with('profile.interests')
->get();
Assuming the User model has a relationship profile and the Profile model has a relationship interests, you can do this.
$interest_id = 1;
$users = User::whereHas('profile', function ($query) use ($interest_id) {
$query->whereHas('interests', function ($query) use ($interest_id) {
$query->where('id', $interest_id);
});
})->get();

laravel load candidates with given skills

In my website users can create candidates (one-many relation) and those candidates can have skills (many-many).
User model:
public function candidates() {
return $this->hasMany(Candidate::class);
}
candidate model:
public function skills() {
return $this->belongsToMany(Skill::class, 'candidate_skill', 'candidate_id', 'skill_id');
}
Skills model:
public function candidates() {
return $this->belongsToMany(Candidate::class, 'candidate_skill', 'candidate_id', 'skill_id')
->withTimestamps();
}
I already have an index page where an user can view ALL his made candidates
$candidates = Auth::user()->candidates;
on the edit page, skills can get synced to the candidate in question
$candidate->skills()->sync(request()->skills);
and back to the index page it shows how many skills the candidates have
<td>{{count($candidate->skills)}}</td>
now, I need to make a search bar. My table already has one(dataTable) to search in the already loaded td's. But I need a search bar to search for candidates which have certain skills, say I want to search for candidates which are synced with 'css' and only show those in the table.
I read through the laravel docs and tried eager loading it:
$hasCss = $candidates->load(['skills' => function ($query) {
$query->where('name', '=', 'css');
}]);
but this just loaded all candidates with only the css skill displayed, even the candidates who dont have it. I want to only load candidates who have the skill and leave the others out.
How do I do this, I'm clueless :s
You're looking for whereHas(...)
Current user's candidates that have CSS skill:
$withCss = Auth::user()->candidates()->whereHas('skills', function ($q) {
$q->where('name', 'css');
})->get();
In your Skill Model, you have an error in your relationship definition. You wrote
public function candidates() {
return $this->belongsToMany(Candidate::class, 'candidate_skill', 'candidate_id', 'skill_id')
->withTimestamps();
}
Swap 'candidate_id' and 'skill_id'. The local foreign key always comes first.
public function candidates() {
return $this->belongsToMany(Candidate::class, 'candidate_skill', 'skill_id', 'candidate_id')
->withTimestamps();
}

Displaying posts of users the user follows through Laravel relationships

I would like to display the posts of everyone the current user follows, ordered by date desc.
I have a many to many relationship supplying all the people the user is following.
$users = User::find(Auth::user()->id)->follow()->get();
I have a one to many relationship displaying the posts for any user.
$updates = App\User::find(?????)->updates()->orderBy('created_at', 'desc')->get();
The question mark's shows where the followers ID's need to be placed.
I can put the above query inside the for each loop but that obviously works its way through each follower rather than all posts in date order.
I suspect I may need to set a new relationship and work from the beginning. Can anyone advise.
User Model
public function updates()
{
return $this->hasMany('App\update');
}
/**
* User following relationship
*/
// Get all users we are following
public function follow()
{
return $this->belongsToMany('App\User', 'user_follows', 'user_id', 'follow_id')->withTimestamps()->withPivot('id');;;
}
// This function allows us to get a list of users following us
public function followers()
{
return $this->belongsToMany('App\User', 'user_follows', 'follow_id', 'user_id')->withTimestamps();;
}
}
Update Model
public function user_update()
{
return $this->belongsTo('App\User');
}
Thank you.
Since you want the posts, it is probably going to be easier starting a query on the Post model, and then filter the posts based on their relationships.
Assuming your Post model has an author relationship to the User that created the post, and the User has a follower relationship to all the Users that are following it, you could do:
$userId = Auth::user()->id;
$posts = \App\Post::whereHas('author.follower', function ($q) use ($userId) {
return $q->where('id', $userId);
})
->latest() // built in helper method for orderBy('created_at', 'desc')
->get();
Now, $posts will be a collection of your Post models that were authored by a user that is being followed by your authenticated user.

Categories