Laravel hasMany not returning collection - php

I am building the middleware for permissions.
Permissions are based on either user action types and/or module/element type (i.e. delete button).
The model ActionPermission (table action_permission) has all the permission types while table users__action_permission is the pivot for User & ActionPermission with all users and their permission IDs.
User
has a permissions() method that gets all the permissions for user
public function permissions()
{
return $this->hasMany('App\ActionPermission');
}
checkUserPermissions (middleware)
public function handle($request, Closure $next)
{
$response = $next($request);
$userId = Auth::id();
$userPermissions = User::findOrFail($userId)->permissions()->get();
dd($userPermissions);
}
Since permissions() is looking for user_id key, and ActionPermission model (table action_permission) does not have the relevant user_id key, I need the table users__action_permission which holds he user_id.
My question is if Laravel has a way for User::permissions() to access users__action_permission table, or do I need to build a model for that?

You do not need a model for the pivot table.
in User model
add
public function ActionPermissions() {
return $this->belongsToMany('App\User', 'users_action_permission');
}
in Action Permission model
add
public function Users() {
return $this->belongsToMany('App\ActionPermission', 'users_action_permission');
}

Related

how can retrive specific data for each user by using eloquent in Laravel

I have two tables in Database, user table and meeting table.
when a user login successfully I want that the information in the meeting table shown to them.
but not all of them just the one which he created them or invited to.
this ids my route:
Route::get('/dashboard/per_user{id}',[meetingController::class, 'meet_for_user'])-
>name('meet_for_user');
this is my controller:
public function meet_for_user()
{
$meetings=meeting::with('users')->get();
return view('dashboard', compact('meetings'));
}
this is user model:
public function meeting()
{
return $this->hasMany(meeting::class,'idCreateMeeting','id');
}
this is meeting model:
public function users()
{
return $this->belongsTo(User::class,'idCreateMeeting','id');
}
If you change how your route is defined to expect a User id, you can use route model binding to inject the User into your controller method and get their meetings from there.
Route::get('/dashboard/per_user/{user}',[meetingController::class, 'meet_for_user'])
->name('meet_for_user');
public function meet_for_user(User $user)
{
$meetings = $user->meetings;
return view('dashboard', compact('meetings'));
}

Loading values from many-to-many realtionship plus values from auto-generated table in Laravel

I am working on some kind of ambulance app and I need help on how to load relationship.
So, I have table appointment_statuses (and it is populated over the seeder because I need only 3 states - Done, In Progress, Not Performed), I have also the many-to-many relationship between the User model and Appointment model (appointment_user table which holds only IDs of both models) and now I am working on EMR system which means I can check all appointments that patient had in history.
Here is the image of the issue
So under "Status" I want to load name of that ID from appointment_statuses table instead to have only ID.
These tables have this structure:
Appointments
Status
These tables have these values:
Appointments table
Appointment statuses table
These are relations:
User:
public function role()
{
return $this->belongsTo(Role::class);
}
public function patient()
{
return $this->hasOne(Patient::class);
}
public function appointments()
{
return $this->belongsToMany(Appointment::class);
}
Appointment:
public function users()
{
return $this->belongsToMany(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class);
}
Appointment_Statuses:
public function patient()
{
return $this->belongsTo(Patient::class);
}
public function appointment()
{
return $this->belongsTo(Appointment::class);
}
Here is a controller which is responsible for emr:
After I have added to controller this:
$user = User::with(['appointments', 'appointments.appointmentStatus'])->where('id', $id)->firstOrFail();
I get this in frontend:
{{ dd($user->toArray()) }}
SOLUTION TO THIS ISSUE
For anyone in future who gets this kind of issue just check the convention about the naming of the foreign keys. In my example, it was the issue, and if you are not sure that your foreign key name is correct then just in the model provide more information like this:
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}
You can use nested relationship
$user=User::with(['appointments','appointments.appointmentStatus'])
->where('id',$id)
->first();
Also you have to modify relationship
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}
For anyone in future who gets this kind of issue just check the convention about the naming of the foreign keys. In my example, it was the issue, and if you are not sure that your foreign key name is correct then just in the model provide more information like this:
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}

How to fetch data from database using nested many to many relationships in Laravel

I'm working on Laravel Access Control Level (ACL) system. where is table contains some many to many to relationship. User table has many to many belongsToMany with Role Table and inversely many to many Role has belongsToMany with User table.Again, Role table has many to many belongsToMany relationship with Permission table and inversely Permission has many to many belongsToMany with Role table.
I want to run a query from user table which is fetch the all permissions of a role. this role is assigned to current user through roles table.
Here is my code sample.
User Model
public function roles()
{
return $this->belongstoMany(Role::class);
}
Role Model
public function users()
{
return $this->belongsToMany(User::class);
}
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
Permission Table
public function roles()
{
return $this->belongsToMany(Role::class);
}
I've tried this query using egar loading...
public function hasPermission($permission)
{
if($this->roles()->with('permissions')->get()->pluck('permissions'))
{
return true;
}
return false;
}
But it always return false.
There are many ways to check if one of the roles has given permission.
One example, add hasPermission method to User.php model
public function hasPermission($permission = '') {
if ( empty($permisison) ) {
return false;
}
/*
Find all user roles that have given permission
*/
$rolesWithPermission = $this
->roles()
->whereHas('permissions', function($query) use ($permission) {
$query->where('name', $permission);
})
->get();
/*
If there is at least one role with given permission,
user has permission
*/
return $rolesWithPermission->count() > 0;
}
Or you can do one query with multiple joins between users, roles and permissions, and filter out the result with where('permissions.name', '=', $permission)

Laravel defining relationship

Am still new to laravel
I have the following tables
user
id
first_name
last_name
educations
id,
user_id //references user id
type
Now in my user model i would like to get a specific users educations which can be many
so a user can have many educations but each education belongs to a single user.
So in my user model i have
public function education()
{
return $this->hasMany('App\ApplicantEducation','id','user_id');
}
In my Education model i have
public function user()
{
return $this->belongsTo('App\User','user_id','id');
}
But the above fails, I cannot retrieve user specific educations
Where am i going wrong?
try this:
in User Model:
public function educations()
{
return $this->hasMany('App\ApplicantEducation', 'user_id');
}
in Education Model:
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
Change return $this->hasMany('App\ApplicantEducation','id','user_id');
to return $this->hasMany('App\ApplicantEducation','user_id', 'id'); you also ommit the id and user_id.
As your foreign_key is well formed, you can also rwite this simple code,
class User{
public function education()
{
return $this->hasMany('App\ApplicantEducation');
}
}
Class Educations{
public function user()
{
return $this->belongsTo('App\User');
}
}
Here,
$this->hasMany('App\ApplicantEducation','id','user_id');
In above statement first argument should be Model second should be foreign key and the third one is any other key from Education model.
Here, second and third arguments are not mandatory.
In User Model
class User...{
public function education()
{
return $this->hasMany('App\ApplicantEducation');
}
In Education Model
public function user()
{
return $this->belongsTo('App\User');
}
Here, additional parameters are not mandatory might be your addition parameters creates issue,
and now you can retrieve your user with Education by
$user = User::with('education')->get();
This can retrieve all the users with their education.
I hope it helps,Thank you, Happy coding.
You should try this:
Education Model
public function user()
{
return $this->belongsTo('App\User','user_id);
}
User Model
public function education()
{
return $this->hasMany('App\ApplicantEducation');
}

Laravel Eloquent Relationship Chain

I'm building a simple notification system.
I'm able to get the logged in users notifications via Auth::user()->notifications but my end goal is to also grab the users info the notification is from.
I'm hoping for an end result of
foreach( Auth::user()->notifications AS $n)
{
echo $n->from->username;
}
currently this throws a "Trying to get property of non-object" error.
Notification table;
id
user_id - notification for this user
from_user_id - notification from this user
User.php;
public function notifications()
{
return $this->hasMany('App\Notification', 'user_id', 'id')->orderBy('notifications.id','desc');
}
public function notificationsUnread()
{
return $this->hasMany('App\Notification', 'user_id', 'id')->where('notifications.seen',null)->orderBy('notifications.id','desc');
}
Notification.php;
public function to()
{
return $this->belongsTo('App\User', 'user_id');
}
public function from()
{
return $this->belongsTo('App\User', 'from_user_id');
}
First you need to have a foreign key set in the table notifications; Then a user can have a notif. and many at the same time. A notif. belongs to a user and many notif. can belong to a user. So on the Notification model you set up the relationship belongsTo like so;
Foreign key:
$table->foreign('from')->refrences('id')->on('users')->onDelete('cascade');
then the relationship:
public function users()
{
return $this->belongsTo('App\User');
}
Then from the controller you can get users info like so;
$userName= Notification::users()->name;
In your case, you're pointing it wrong inreturn you will get only the relationship type instead of data object, since you are calling from like a non method. You should do something like this:
foreach( Auth::user()->notifications AS $n)
{
echo $n->from()->username;
}

Categories