تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Defining Posts and Comments0:00

Okay, so moving on. For this next episode of How Do I, it comes from Wade Hasan. Sorry if I'm speaking that wrong. And he essentially wants to know, how do you go about getting the last replied record? Or imagine you have a list of articles or threads or posts, and you want to get the username of the most recent reply. So yeah, maybe you have posts and comments, and we want to know, what is the username of the most recent post? How can we do that? Okay, I'll show you a couple techniques. I have a fresh install of Laravel. The only thing I've done, like usual, is set up a simple SQLite database, and we're all set to go. php artisan make:model Post -m, and I want a migration with that. And then we'll do the same thing for a Comment. That looks good. And now, if I switch over to there, we'll quickly set up our migration. A post, for now, we'll just have a title and a body. And then, of course, a post is written by

comment. That looks good. And now, if I switch over to there, we'll quickly set up our migration. A Post, for now, we'll just have a title and a body. And then, of course, a Post is written by a User. Okay, that looks good. Next, let's go to Comments, and just about the same thing. So a Comment, well, it belongs to a Post, right? And it also belongs to a User, user_id. And then finally, we'll have the body of our Comment. Okay, so basic stuff. Now, if I run php artisan migrate, we have a users table, a posts table, and a comments table. So next, I'm going to go to my database/factories/ModelFactory folder or file, and we're going to set up a few factories that'll help us when testing all of this out. So I'll give you some real estate. We want a record for a Post. And yeah, this will consist of the title. I kind of wish Laravel will do this for us. There's definitely a way to

Building Model Factories1:38

So I'll give you some real estate. We want a record for a Post. And yeah, this will consist of the title. I kind of wish Laravel will do this for us. There's definitely a way to parse the columns and then figure out the proper fake value to use. Maybe that will one day get added. Anyway, so Post has a title and a body. That'll be a paragraph. And then, of course, a Post belongs to a User. Now, you can do this, but quick little tip, always wrap it within a closure and then return that. So we could say, App\User::create('id' => $id). Yeah, I mean, you could do this. So for example, if I did this number right here, it would still work. However, anytime you override it, so when you say, App\Post::create('user_id' => someHardCodedValue), but I want to override the user_id to be this hard-coded value. Well, if you do it like this, no matter what, it's going to create a User. And then, yes,

php artisan post create, but I want to override the userId to be this hard-coded value. Well, if you do it like this, no matter what, it's going to create a User. And then, yes, it will replace the userId with what you specify here. But behind the scenes, it is building up a User in the database. However, if we wrap it within a closure, that basically keeps that from happening. So when you override userId to be five, it never triggers this function, and you don't needlessly create a User in the system. Okay, good little tip there. So for Post, we have a userId, a title, and a body. I think that's good. We're going to do one more now for a Comment. A Comment consists of a User. It consists of, let's duplicate this, a postId, and then the body itself, right? And I think that should do it. Okay, so now we can do stuff like this. If I run, I have a little aliases here,

Generating Test Data3:07

let's duplicate this, a post ID, and then the body itself, right? And I think that should do it. Okay, so now we can do stuff like this. If I run, I have a little aliases here, that's another tip. I try not to use them in the videos just so as not to confuse people, but I have things like tinker, migrate will run php artisan migrate, artisan is an alias for php artisan. So those things are really going to save you quite a bit of time. So if you're always doing this, just say artisan make:model and create an alias. Or if you're always saying php artisan migrate, just change it to migrate. Trust me, it's worth it. Anyways, if I boot up php artisan tinker, I can now say, give me a factory for Comment. We'll create that. And now it's going to also, of course, create a User and a Post in the process. So if I say Post first, there we go. ID of one. So why don't we do this? Let's create a handful of comments, but we will set the post

of course, create a User and a Post in the process. So if I say Post first, there we go. ID of one. So why don't we do this? Let's create a handful of Comments, but we will set the post_id equal to that one we just created. Just so we have one Post that consists of a lot of Comments. So app\Post::class on, you know what just occurred to me, I think I set the post_id to five. Let's see. Yeah, sorry, I'm still have five on the brain. So let's do this. Let's whip up a factory for a Post. Create. ID is two, ID is three. We're just going to do it the slow way. Okay. So now I could say app\Comment::class where the post_id is five, and then just pluck out the IDs, and we should see about five different Comments. So now let's create a brand new Comment for that, just so we have the most recent one, and they don't all have the same timestamp. So I'm going to go back a couple clicks,

Fetching Latest Comment4:51

just so we have the most recent one, and they don't all have the same timestamp. So I'm going to go back a couple clicks, like so. So this should be the newest Post, right? Give me the most recent Comment for this Post. Okay. Well, one way, the manual way you can do this is something like this. Well, I can't reference a relationship right now, and of course that's because we haven't set it up. So why don't we do that very quickly? A Post consists of Comments, and that relationship is a hasMany, right? Layer of a 101 stuff. So if we close this out and boot it up again, I could say, give me the Post with an ID of five, and now I want all Comments associated with that Post, and now we'll get a collection. And we can see that should be like five or six. Yeah. But what if we said Post::comments()->latest()? So that means order by the created_at field.

post, and now we'll get a collection. And we can see that should be like five or six. Yeah. But what if we said post comments latest? So that means order by the created_at field in descending order. Remember, you can always hunt that down. Order by created_at in descending, which is what we want, and then give me the first result. And sure enough, yeah, that's giving us the most recent comment for this post. But yeah, this isn't overly fun to write. And further, we don't necessarily want the comment, we wanted the user. So we could go to comments and set up a relationship there. So we could say Comment belongsTo a User, right? This belongsTo User. Okay, so let's do it again. Let's grab a post. And now I could say post comments latest first user. And sure enough, we can see that this person has written the most recent comment on the post. Okay, but yeah, that sucks. So instead, maybe we could say something

Encapsulating with Methods6:23

comments latest first User. And sure enough, we can see that this person has written the most recent Comment on the Post. Okay, but yeah, that sucks. So instead, maybe we could say something like this. We could say Post. Well, let's start with latestComment. We're going to start with that angle. So yes, we could just copy all of this and paste it in. And then remove that and then say return this comments like so. Yeah, I mean, that would work. So we're just wrapping it at that point. We grab our post, and then we say latestComment. And that should return a Comment record. And we get the same one. Or another way is to do something like this. The latest Post, well, that relationship would be a hasOne. And we could say hasOne Comment. And we do want this to be in descending order by the created_at timestamp. So that would work as well. At which point we would do this post latestComment. And now that's going to give us the record, the exact

to be in descending order by the created at timestamp. So that would work as well. At which point we would do this post latestComment. And now that's going to give us the record, the exact same record. So now yeah, you can still delegate. So you could say latestComment and then give me the User associated with that. And then give me her name or his name. So what we can do is put this on our Comment model. And we could say if we want the username, then here can be the wrapper for it. Give me the user relationship and find their name, or it might be a username in your system. Alright, so now yeah, we could do this. We could say give me the post, give me the most recent comments. And then we could also say on that comment, give me the username for that person and we get the user. Finally, if you want to go one more, and you could say what's a good method name, latestCommentUsername, I don't know. Anyways, we could say return. Yeah, give me the

and we get the User. Finally, if you want to go one more, and you could say what's a good method name, latestComment, username, I don't know. Anyways, we could say return. Yeah, give me the latestComments. And then I want their username. So finally, one more time, give me the post. And I want the latestComment username. And once again, we grab that. So yeah, you don't have to do this. If you want to go directly through the relationship, that would be fine. It just depends upon how you want your API to work. Like I said, if you really have no interest in the latestComment directly, the only thing you care about is the latestComment username. Yeah, then you could always replace this with this->comments()->latest()->first()->username, like this, and then get rid of that method entirely. And I think that will still work. And it does. So yeah, it just depends upon what you need for your project. Okay, now let me show you one more thing. And then I promise we'll

Using Joins for User Data8:51

that method entirely. And I think that will still work. And it does. So yeah, it just depends upon what you need for your project. Okay, now let me show you one more thing. And then I promise we'll call it a day. We could also use joins here. So for example, if we once again, we grab the Post with an ID of five, and then we say post.latestComment, take a look at the results, we get all of the columns for the Comment. But if you know you're always going to want information about the User when you fetch that, then you can always just join the users on the condition that the User's ID equals the Comment's user_id. Okay, so notice the difference, we only have records about comments. But now if we do it again, now in the process, you've also pulled in information about the User. And further, if you want to add a select on top of that, like you're only ever going to want the title, the body, and just a couple other things like the user's name, things like that,

the User. And further, if you want to add a select on top of that, like you're only ever going to want the title, the body, and just a couple other things like the user's name, things like that, then that would be fine. So if we come back one more time, now on Yeah, in this case, it's squawking because the created_at column is ambiguous. So it's letting you know, well, do we want to sort according to the users table that we joined in that created_at column, or the comments created_at. So we want comments. Okay, one more time, all I'm saying here is you can be as flexible as you need to be. So when you call post latest comments, if the only thing you need is a couple records or a couple columns for the post, and then the name of the user, well, now you can do that. And that's a pretty clean way to go about it, at which point, you wouldn't even need this. And further, it's possible on the comment, you can keep this that can have its use.

And that's a pretty clean way to go about it, at which point, you wouldn't even need this. And further, it's possible on the Comment, you can keep this that can have its use. But if you never reference it in your project, then it doesn't need to be there. Okay, so yeah, I think joins aren't used enough. Sometimes people think everything has to be done with ActiveRecord and these proper relationships like belongsTo or hasMany. But yeah, sometimes just referencing a simple join is a great and efficient way to go about it. Alright, so that does it for this episode. If you have a question that you'd like to have answered in video form, ideally, tweet your question. And then at the end, hashtag #helpmeLaravel, and I just might provide an answer. Okay, see you later.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟