How to access other fields on a three way pivot in Laravel? - laravel

Here's what my architecture looks like:
The idea is that a user have a role on a given group. Of course, the user belongs to many groups, and a user can have multiple roles (in different groups)
I'm trying to get all the groups a user belongs to.
Please forgive me for not using the convention to name the pivot table as groups_roles_users, I decided this way for readability.
So, in the User model I say:
public function groups() {
return $this->belongsToMany('\App\Group', 'roles_in_groups');
}
In a view I do:
#foreach ($user->groups as $group)
{{ $group->name }}
#endforeach
works perfectly.
Now I want to access the roles table. I want to print something like: In {{ $group->name }} you're a {{ $group->role->name }}, obviously, It doesn't work like that.
If I use the pivot property, it will give me only the user_id and group_id, not even the role_id to search with an static method.
SO, how can I accomplish that?
I'm using Laravel 5.7

Maybe try:
public function roles() {
return $this->belongsToMany('\App\Role', 'roles_in_groups');
}
$user = \User::with(['roles','groups'])->first();
$role_name = $user->role->name
$group_name = $user->group->name
https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

Related

Laravel belongsToMany get one record

I have three tables as below:
users
id|name|username|password
roles
id|name
users_roles
id|user_id|role_id
These tables communicate via belongsToMany.
Table users_roles has many records. The user can change his role, but I have to store every change.
id
user_id
role_id
1
2
2
1
3
2
1
2
3
1st. How can I get the last and single role_id with the user?
$users = User::with('roles')->get();
Now I'm getting user(2) with two roles, but I need user(2) with single and last role(3).
2nd. How I can access roles->name on the blade?
#foreach($users as $user)
{{ $user->name }} <<< normal
{{ $user->roles['name']}} <<I'm getting error here
roles will be a collection so you could just use the last() method and have something like:
$user->roles->last()->name;
Alternatively, if you can update to Laravel >= 8.42, you could use the Has one of many relationship.
Create a new relationship in your User model:
public function latestRole()
{
return $this->hasOne(Role::class)->latestOfMany();
}
Then you would load the role with latestRole:
$users = User::with('latestRole')->get();
This way you can access the relationship directly:
#foreach($users as $user)
{{ $user->latestRole->name }}
You can use whereHas
$users = User::with('roles')->whereHas('roles', function ($q) {
$q->latest();
})->get();

I have a laravel project with 2 tables (users and roles). In a roles view, I am trying to display a count of users who are using that specific role

My tables areas follows
roles table (id, roleName, roleDesc)
users table (id, name, role, email)
When adding a new user, I insert a role eg "Admin" into the role column of the user.
My problem is that I want to show the number of users who have that role in a view data table that displays list of roles. Eg would simply be an integer of number of members who share that role, eg 5.
In my roleController, I am fetching records using
$roles = Role::all();
$users = User::all();
I have managed to display a count of users with role "Admin", but this ofcourse just duplicated all down the datatable with eg "1"
$RoleCount = User::where('role', '=', 'Admin')->count();
So, I think I need to use a join or something to replace the 'Admin' above, with current roleName.
I hope that makes sense and I hope someone can help me find a solution. I know this is pretty elementary, but trying to rap my head around joins and having a bit of trouble.
Thanks in advance.
First it will be great to use Relationships (Laravel docs)
With relationships it will be super easy.
Change Users table, so you have there NO the name of role, but ID of role = columns id, name, role_id, email
In Role model add relationship to User, and in User model add relationship to Role:
Model User.php - add method
public function role(){
return $this->belongsTo('App\Role'); //use your correct namespace
}
Model Role.php - add method
public function users(){
return $this->hasMany('App\User'); //use your correct namespace
}
And then just select all roles with count of users:
$roles = Role::withCount('users')->get();
In your view:
#foreach($roles as $role)
{{ $role->roleName }} - {{ $role->users_count }}<br>
#endforeach

I am trying to return users and items datas from invoice

this is my function in Invoice Controller
public function edit(invoice $invoice, $id)
{
$invoice = Invoice::with('users', 'items.products')->findOrFail($id);
return view(compact('invoice'));
}
in my View I did
{{ $invoice->user_id->email }}
The relationship you are loading is named users so that is the name of the dynamic property for that relationship. user_id is the User's id, not the relationship.
{{ $invoice->users->email }}
This is also assuming there is always a User for the invoice.
Laravel 6.x Docs - Eloquent - Relationships - Relationship Methods vs Dynamic Properties
Side Note:
The naming could use some work since there should only be one user for an invoice I would assume, so singular. Use plural when something can have many, singular when it has one or none. The relationship should be named user.
You are using the wrong property, $invoice->user_id is probably is the raw integer value coming from the database. You need to call the relation like so:
{{ $invoice->user->email }}
$invoice->user will return the user object that is related to the $invoice->user_id id.
you forgot view name to return
public function edit(invoice $invoice, $id)
{
$invoice = Invoice::with('users', 'items.products')->findOrFail($id);
return view('invoice.edit',compact('invoice'));
}
and access with relationship name
{{ $invoice->users->email }}

3 relationships within each others for subscription

I have hashtags and users can subscribe them. here is what I did for subscription:
function hashtag(){
return $this->belongsToMany('App\Hashtag');
}
And also there is user relationship in Subscription Model:
function user(){
return $this->belongsToMany('App\User');
}
The user Model has subscribes which is supposed to give me the hashtags that the Authed user subscribes. Here it is:
function subscribes(){
return $this->hasMany('App\Subscription');
}
Now with this code I tried to access the hashtags the Authed user subscribes here is the view code:
#foreach(Auth::user()->subscribes->hashtag as $tags)
{{ $tags->name }}
#endforeach
What I think is that, laravel expects a relationship table here, called hashtag_subscription or something like that. Now I got a bit confused with these relationships. I highy prefer to get around this withput creating extra table, I feel like I can accomplish it without an extra table.
Tables are as following:user, hashtag, subscription
Models: Hashtag, Subscription, User
You need to change your relationships first, because as I understood you one Subscription model has One-To-One relationship to both User and Hashtag:
function hashtag() {
return $this->belongsTo('App\Hashtag');
}
function user() {
return $this->belongsTo('App\User');
}
Then you can loop through user subscriptions and have access to both Hashtag and user to whom the initial user is subscribed to:
#foreach(Auth::user()->subscribes as $subs)
{{ $subs->user->firstname }}
{{ $subs->hashtag->name }}
#endforeach

Laravel Many To Many Method Issue

I have a many to many relationship between the models User & Notification.
User Model:
public function notifications()
{
return $this->belongsToMany('Yeayurdev\Models\Notification', 'notifications_user', 'user_id', 'notification_id')
->withPivot('notifier');
}
Notification Model:
public function user()
{
return $this->belongsToMany('Yeayurdev\Models\User', 'notifications_user', 'notification_id', 'user_id');
}
Pivot Table:
ID USER_ID NOTIFICATION_ID
1 2 1
In my view, I retrieve a list of all notifications for a user like so.
#foreach (Auth::user()->notifications as $notification)
{{ $notification->user->username }}
#endforeach
The problem is that when I try to get the username of the user with that notifications, I get the error Undefined property: Illuminate\Database\Eloquent\Collection::$username. "Username" is the column on my users table which is just a string. I don't see where I'm going wrong because if I just do "$notificatin->user" it gives me the collection.
Thanks!
As you said, the relationship is many-to-many, so $notification->user in your case is returning a collection of User models, NOT a single user. If you need only a first user then just do
{{ $notification->user()->first()->username }}
If you need to print out all users for every notification, then you will need a loop here to go through all users.
#foreach (Auth::user()->notifications as $notification)
#foreach($notification->user as $notificationUser)
{{ $notificationUser->username }}
#endforeach
#endforeach
I would recommend renaming user() relationship to users() to avoid confusion in the future.

Resources