Create pivot table migration0:00
Let's bring the missing piece in terms of the shape of our data between Puppys and Users. The liked status, Okay, a User can like multiple Puppys and a Puppy can be liked by multiple Users. So this is what's called a many to many relationship and we are going to set that up with the pivots table in our database. So let's create a new database migration with php artisan make:migration.
So let's create a new database migration with php artisan make:migration. So the convention here is to take the two models that are involved in the relationship, so Puppy and User, and then alphabetically sort them to make the name of the migration. So we'll call this create_puppy_user_table.
Puppy comes first and it's going to be singular puppy_user table. So let's create that. There we go. We have our puppy_user table with the up and down methods. And so by default we have an ID and timestamps. We'll keep that. And then in this table we want to keep track of two things, the ID of the user and the ID of the puppy involved in the relationship. So table foreignId four. Let's start with the Puppy class.
So table foreign ID four. Let's start with the Puppy class. And we probably want to constrain this and cascade on delete. And then I will duplicate this and do the same for the User class. So this is going to translate to a puppy_id column name. And this one is going to be user_id column name. And while we are here, we want to do one more thing.
Enforce unique likes1:39
And this one is going to be user_id column name. And while we are here, we want to do one more thing. We wanna make sure that the same User cannot like the same Puppy more than once. So let's have a unique constraint here and I'm going to add table->unique and it knows exactly what I want to do. And what it's saying is that the combination of a puppy_id and user_id should never occur more than once. So let's run this migration. php artisan migrate.
Test pivot data1:58
and userId should never occur more than once. So let's run this migration. php artisan migrate. And there we go. We have a new pivot table to handle our many to many relationship. Okay? And here it is. This is a very simple table. So let's try to create one manually. The puppyId is gonna be one, the first puppy and the userId is one, which is Simon. And let's create another one where the ID is three and the user is one because we only have one user so far.
And let's create another one where the ID is 3 and the user is 1 because we only have one User so far. And so when I save this, we've created these two relationships, but let's also test the uniqueness. So if I was trying to create another one and one relationship, which technically is the same as this one, when I hit save, it's going to tell me, Hey, you cannot do this because it's not unique. So it's working. Very cool. So let's delete that row. So we have the relationship modeled in the database,
Add model relationships2:43
So it's working. Very cool. So let's delete that row. So we have the relationship modeled in the database, but now we need to mirror this in the User and the Puppy models. So let's start with the Puppy model. Remember, we've created a User relationship which is belongsTo, and we are going to create another one public function, uh, likedBy which this time is a belongsToMany relationship. And here we're going to have the same as for the User,
to many relationship. And here we're going to have the same as for the User, but it's going to be a belongsToMany. Instead, there we go. And we want to do the counterpart in the User model. And here a User can have multiple Puppys and now we are going to add public function likedPuppies and it's also going to be a belongsToMany. So manyToMany relationships are belongsToMany both ways.
and it's also going to be a belongsToMany. So many to many relationships are belongsToMany both ways. And here, let's copy that and change the relationship to belongsToMany. Alright, so with this in place, whenever we are fetching a User, we should be able to access its liked puppies through the likedPuppies method. And whenever we fetch a Puppy, we should be able to call likedBy to see what users have liked this puppy.
And whenever we fetch a Puppy, we should be able to call likedBy to see what users have liked this Puppy. And this is the one that we are going to test out right now. Whenever we display our Puppys, we will want to be able to check this likedBy status to see if it matches the current logged in User and show the loved heart if it is. But before we do that in the UI, let's bring back our json_encode dump of data and see if we can see the relationships.
Expose likedBy in API4:14
let's bring back our JSON stratify dump of data and see if we can see the relationships that we've manually created in the database. So because we are using JSON resources, I am going to update the PuppyResource to also, I'll put it above the User, have a likedBy property and uh, I guess I'll accept what copilot wants, but it's a little bit heavy handed as of now. If the likedBy is loaded, which we are going to handle, we are going to return a whole collection of Users,
If the likedBy is loaded, which we are going to handle, we are going to return a whole collection of Users, which is the UserResource. So let's start with that as a proof of concept. But we are then going to trim it down a bit. Let's bring a good friend pre tag here once again. And right now it is not showing anything because we are not loading the likedBy relationship. But if I go in the web.php routes and I decide to also load likedBy, I'm hoping
But if I go in the web that php routes and I decide to also load likedBy, I'm hoping that we should see a list of Users that have liked the puppies just before we switch to the UI. Remember, we've manually created two relationship instances in the database. One for the User one, which is me and the Puppy one, and then one for the User one again, and Puppy number three. So I'm expecting in the UI to see the Puppy one and three have the User ID one Simon in the likedBy.
So I'm expecting in the UI to see the Puppy 1 and 3 have the User ID 1 Simon in the liked by and the other should have nothing. So moment of truth, let's check it out. All right. And so Bella, which is the Idea 1, was one of the relationships that we had created with Simon here. And so ID of 2 should have nothing. It has the User, but this is not the likedBy relationship. You can see this one is empty. And then the Idea 3 also has this relationship.
You can see this one is empty. And then the Idea of three also has this relationship. This is working perfectly. Let's just to verify, create a relationship with the Idea of six. So this should populate Simon here. So puppy of six liked by Simon. Save this and refresh the page. And sure enough, there it is. Excellent. So at this point, we have everything that we need.
Return user IDs only6:08
And sure enough, there it is. Excellent. So at this point, we have everything that we need to implement the UI with our backend data that we've created. But at the moment, we are passing the whole User object for the likedBy, and I dunno if you remember from the Vanilla React course, but the likedBy array was just an array of User IDs. And so if we look at something like the PuppiesList component, if we go find the likedBy here,
And so if we look at something like the PuppiesList component, if we go find the likedBy here, the likedToggle, you can see that this is expecting a puppyId. So basically it's checking if the puppy likedBy includes the userId. And so if we keep the data as we have it, now we can make it work. But we are going to have to update some of this code. And while we shouldn't have to change the backend
But we are going to have to update some of this code. And while we shouldn't have to change the backend to please the front end, if we look at the ui, all we're trying to do with this disliked status, the liked by is to toggle the heart on and off. So we really don't need to have the username, we just want its id. So I think here it makes sense to just return the ID of the User in the relationship instead of the whole username and id.
of the User in the relationship instead of the whole username and id. So let's update our Puppy resource. And so here, instead of returning the whole User resource for each user that liked the Puppy, we can pluck out the ID field only. And so that should just give us an array of user IDs, which is precisely what we want. Let's verify that. And yep, liked by one and Puppy number six should also have liked by one.
Let's verify that. And yep, liked by one and puppy number six should also have liked by one as it is right now, exactly like this. The shape of this data is now compatible with the puppies list. So we should be able to replace our ui. So we can go multiple directions from here. We still need to handle User creation. So not all puppies are just liked by me, although I do like all of them.
So not all puppies are just liked by me, although I do like all of them. So we could tackle this and have a login, logout links that allow users to create accounts easily. But I think that we've waited long enough playing with this data that we should now see if we can replace it with the actual UI and get rid of our placeholder json string, and also this very ugly list of puppies that I've created.
and get rid of our placeholder Json string, and also this very ugly list of puppies that I've created. So we want to take that and instead of that, we want to use that. Let's do that in the next lesson.
