Playing
03. Polymorphic comments

Transcript

00:00
Because our comments need to be attachable to any model.
00:03
We want to be able to drop that in. We're going to need to work with a polymorphic relationship. Let's go ahead and create out the comments table, first of all. And then we'll go ahead and play around with this data and
00:14
see what we can do with it. So we'll go ahead and make out a model. This is just going to be a single comment model. And let's start to fill this in and think about what we might need here.
00:24
Okay. So let's start with the obvious stuff. We are going to need a foreign ID for the user, of course, who is actually posting this comment.
00:33
Let's make this nullable. There's a very good reason for that. And let's go ahead and make this constrained. Now, the reason that we've chosen nullable here is that if a user is ever deleted,
00:42
we're going to set this user ID to null and we're going to soft delete the comment. So it's not shown within the list of comments. So it will still be retained and it's a really good idea to retain comments that have been deleted.
00:56
And we'll just go ahead and not show it. Okay. So for this, then, because of that, we're going to say null on delete. So when this user gets deleted, this will automatically be set back to null.
01:08
And of course we have this set to nullable. Okay. So the next thing, the most easy is going to be the text of this, which we'll just call body.
01:17
And I mentioned soft delete. So let's go ahead and add them in. Now we have a handy helper, which will add a deleted at column. Now the more complicated part of this is not necessarily the polymorphic
01:28
relationships, but the fact that we want to have to have child comments. So we want to have replies, but the parent is going to be the same model. So let's add in the polymorphic relationships. And if you're new to polymorphic relationships, we'll see
01:42
how these look in a minute. We're going to set this to nullable morphs and we'll have commentable here. Now, the reason we're setting this to nullable morphs is that any of the child replies won't have a commentable ID and a commentable type.
01:58
So once we've run the migrations here, I'll explain a little bit more, but let's think about the relationship for replies. So reply is going to have a parent ID. So let's add in a foreign ID in here and we'll say parent ID.
02:12
So this parent ID will reference the parent comment that this was replied to. Again, this needs to be nullable because a top level comment will not have a parent ID because it will be at the top level and we want to constrain this to the database level, but we need to specify that we want to constrain
02:29
this specifically to comment. Unlike here, this isn't going to be able to pick up the fact that this is for a comment. So we have a different name for the column.
02:38
Okay. We're pretty much done. Let's go ahead and just migrate this and then let's look at the schema and I'll explain a little bit more.
02:46
Okay. So let's go and open up our comments table here. And as you can see, it's created a commentable type and commentable ID. Now, if you are new to polymorphic relationships, commentable ID will be
02:57
the thing that we're commenting on the ID of the thing that we're commenting on. So if we have an article with an ID of one, this will be one commentable type by default will be the full namespace to the thing that we're commenting on. So for example, this might be app models and article, if we're commenting on an
03:16
article, and that means that when we try and get comments for a specific type and a specific ID, it will find this in the database automatically for us with that our first relationships. Now the parent ID, again, we've already seen if we created a top level comment,
03:30
the parent ID would be null because it's an initial comment. But then when we reply, the parent ID will be the ID of the comment that we're replying to. Okay.
03:39
So let's go ahead and leave it at that. And then as we get through and start to create comments, we'll see this come together. So our goal now is to create out a comments, live wire component, and then
03:50
have this display the data for this specific article, and then we could even manually create some data in the database just to see what we've got. So let's start to create out another live wire component here. And of course, let's call this comments and let's go and add this to the page.
04:08
So over in our article show, we want to down here, output all of our comments. So let's go and add in live wire and comments. And we saw from the introduction that we want this to be bound to a specific model. Let's pass that in now, cause that's not too much trouble.
04:27
We just want to pass in the article itself. So if we head over to our comments component, we know that we're going to get a model passed into here. Now, really importantly, we're not going to type in this down to say article
04:39
because it might not be an article. So we're just going to type in this down to a model itself like so. So from the model, what we can now do is extract all of the comments out regardless of which model it is.
04:53
But the only problem is we don't have a relationship just yet. So if we head over to our article, let's create out a relationship for all of the comments for this. So to define a one to many polymorphic relationship, we are going to go ahead
05:08
and create out the method name as usual. And then down here, we're going to use morph many. So let's go ahead and pull this relationship type in. We know that this has many comments, so we're going to go ahead
05:21
and provide in comments class. And then we're going to give the name of the sort of morphable thing that we created in this case is commentable. Okay.
05:29
First of all, it looks like we're pulling in comments for the relationship type here, which is not what we need. We want this to be the comment model. And now let's head over to our comments component and let's
05:41
die dump out on this relationship. So let's access our model and let's grab all of the comments for that specific model. So as you can see here, we are getting a collection back.
05:52
There is nothing in there at the moment. Let's go over to the database and just manually add some data in here, just to see what this looks like. And then we're going to talk about this commentable type and how we
06:01
can make this a little bit better. So I'm going to go ahead and set this to a user. Now we don't have a user at the moment. So just before we do this, let's go ahead and register out an account in here.
06:10
So we can use this to eventually post some comments. Okay. So I'm going to head back over to articles and an article, and now we can go over and just set that to user ID one, I'm just going to say, Hey, in here.
06:22
Now the commentable type, when we insert this, when we create a comment is by default going to be the location to the thing, and that's going to be an article. The commentable ID will of course be one. That's the ID of the article.
06:36
Parent ID is going to be null. And we will of course, automatically get filled in a created app and updated that day. So that is pretty much how an article or a comment is going to look in the database.
06:48
If we head back over to the browser, give this a refresh. Sure enough, we now have a comment in here that we can of course display on the page. Now, one thing I really don't like to do is have the commentable type set to the full namespace of the model.
07:02
It's going to be really annoying if you move the location of the model, then you're going to end up with no comments for this particular thing. So instead, what we're going to do is change this over to just a single word or whatever you want to add.
07:16
And we're going to use a morph map to change this over. So if we head back over to the browser, you can see at the moment, this doesn't work because it can't find anything under that namespace, but what we can do is head over to our app service provider or anywhere that we want to do this and
07:30
under boot use the relation class, which is under eloquent relations to enforce a morph map, so let's add enforce morph map. And then in here, we just want to pass an array with the thing that we want to see this stored as in the database or read from in the database, and we want to map
07:49
that to the model class that we want to use the fully qualified namespace, the class, which would normally be the string that goes into the database. We're instead going to say, well, we want that to be represented as an article. So when we insert comments for a particular article, now it's going to store this as
08:08
article, and when we read, it's going to look for article. So if we head over to the browser and now give that a refresh, you can see sure enough that it's hooked up just like we had before. Okay.
08:19
So now that we've done this, let's go and just tidy up what we've got inside of our comments component, and instead of die dumping this, which of course doesn't make any sense, we're going to return this to the view so we can do something with it. Output all of the comments.
08:34
Let's go ahead and just send them comments down. We are going to making, uh, be making some adjustments to this later, but that should be enough for now. So if we head over to the browser, yeah, sure enough, we're back to square one and
08:45
we can start to iterate through all of our comments when we need to. Now, before that, we're going to head over to the next episode and look at storing a comment, so I'm just going to get rid of this in the database and we'll build out this form, be able to click to post a comment and see it in the database.
18 episodes1 hr 40 mins

Overview

Build a drop-in comment system with Livewire that instantly works for any model.

We’ll cover top-level comments and replies by re-using Livewire components, editing and deleting comments, working with Alpine.js to minimise network requests, building an Alpine.js directive to display when a comment was posted, handling deleted users and loading more comments gradually.

Once you’re done, you can drop a single Livewire comments component wherever you need it — and comments will instantly be enabled.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Comments

No comments, yet. Be the first to leave a comment.