3 relationships within each others for subscription - laravel

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

Related

Getting 2 lots of relationship data from a Laravel collection with Yajra Datatables

I am trying to get my Yajra Datatable working correctly but struggling.
Basically I want to get all clients appointments in which the client belongs to the logged in user. I then want to access the Client name and then the appointment data. I have used the following to get the appointment data
$user = User::find(Auth::user()->id);
$data = $user->clients()->with('appointments')->get()->pluck('appointments')->flatten();
return Datatables::of($data)
->make(true);
This allows me to show a row for each appointment that exists for the user-owned clients appointments. But how can I also access the clients name from this?
I have tried many different ways but if I use something like
$data = $user->clients()->with('appointments')->get();
I can access all of the data I need but it shows the existing clients in each row, not all appointments owned by the clients.
My setup is
User Model
public function clients(){
return $this->hasMany(Client::class);
}
public function appointments()
{
return $this->hasManyThrough(Appointment::class, Client::class);
}
Client Model
public function appointments(){
return $this->hasMany(Appointment::class);
}
public function users(){
return $this->belongsTo(User::class);
}
Appointment Model
public function client(){
return $this->belongsTo(Client::class);
}
Thank you
You might be looking for whereHas:
$appointments = Appointment::with('client')
->whereHas('client.users', function ($query) use ($user) {
$query->where('users.id', $user->id)
})
->get();
This translates to: "Give me all the appointments that belong to clients of a specific user".
Just a suggestion, it might be wise (not required at all) to alter your database structure to something more flexible. What if you for instance keep track in you appointment which user is present?
appointments
- user_id
- client_id
This would make your query a bit simpler
// In User
public function appointments()
{
return $this->hasMany(Appointment::class);
}
$user->appointments()->with('client')->get();
You could go even further by making the relation between User and Appointment, Client and Appointment many to many so you could have appointments with more than one user and/or client.

Multiple lookup to the same table in laravel

I'm a beginner learning laravel and ran into a strange problem. I would like one table to reference the same lookup table twice. For example, if I had a messages table which stores messages between two users.
If my messages table structure is like:
id - unsigned (auto incrementing pk)
message - string
user1_id - unsigned
user2_id - unsigned
How should I set up the messages and users models so when displaying an index of the messages, it shows the user.email for user1 and user2 from the users table?
If there was just 1 user per message, I could name the column 'user_id' and then have a belongsTo relationship to the users table.
It seems like it might involve using the $appends property, but how should things be configured to retrieve the 2 users' email addresses when querying the messages table and send those along with the the message data to the view?
Someone helped me on the laracasts forum and I figured I'd post the answer here in case it's helpful.
The answer is to set up additional relationships in the message model. Like:
public function userOne() {
return $this->belongsTo('App\User', 'user1');
}
public function userTwo() {
return $this->belongsTo('App\User', 'user2');
}
Then in the view, assuming you passed the messages as $messages, in the foreach $messages as $message loop, use the optional() helper to get the data like this:
{{ optional( $message->userOne)->email }}
public function userOne() {
return $this->hasOne(User::class, 'id', 'user1_id');
}
public function userTwo() {
return $this->hasOne(User::class, 'id', 'user2_id');
}

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 }}

How to access other fields on a three way pivot in 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

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