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

Writing Assignment Test0:00

Now that we have an Achievement model in place, let's figure out how to associate any given User with any given Achievement. So I'm going to switch back to our feature test here, and we'll add a test at the top. A User can be assigned any Achievement badge. Okay, so let's think about it. Let's write it out. Well, given we have a User, as well as some Badge, so as well as a Badge, if a Badge is awarded to a User, then it should be accessible through the achievement relationship, something like that. Okay, so let's do it step-by-step.

like that. Okay, so let's do it step-by-step. First, let's create a User. And create that, save it to our User. Next, we need an AchievementBadge, which we have available now, thanks to the last episode. What else? If a Badge is awarded to a User. Okay, so this is where we figure out our API. If we're thinking as simply as we can, I see a couple choices.

Choosing Awarding API1:06

Okay, so this is where we figure out our API. If we're thinking as simply as we can, I see a couple choices. One would be something like User Award Achievement, that would be an option. Or do we want to be explicit? What are we awarding? Something like that. Because here, I like the way that looks, but I also think down the line, if I see a method called award, do I know that's awarding an Achievement? Maybe it's awarding experience points. Maybe it's awarding a best dancer on the forum.

It's very clear how you would naturally think. The downside to this approach is almost everything sounds good on User, and this is why your User model is almost always the first candidate for abuse, especially a year down the line. If everything looks good on User, then you throw everything on User. And then it starts getting kind of muddy, so you begin extracting single use traits to help with that. And it does help, but again, just be a little careful with that. So with that in mind, my initial instinct is to go with this second or this third option, Achievement Award to User. Or at the very least, we're going to try that to begin.

achievement award to User. Or at the very least, we're going to try that to begin. And if we don't like it, we'll switch back. Okay, so if a Badge is awarded to a User, then it should be accessible through the achievements relationship. So I do want to make sure, no matter what, that I can still do this. That's important to me. So let's say this assert count of one, and then we'll make sure it's the exact Badge in a moment. But yeah, here we have the beginnings of our actual test.

in a moment. But yeah, here we have the beginnings of our actual test. All right, so we'll give it a run. Award two does not exist. Okay, well, let's switch over. And we have a method. All right, give it another run. assertCount must be countable. Yeah, so this is a common one. It's trying to check the count of something that should be countable, but this achievements

Creating Pivot Migration3:17

Yeah, so this is a common one. It's trying to check the count of something that should be countable, but this achievements property or attribute is returning null. So of course, it's going to error out. Let's make it work. If we switch back, well, think about it. We have an achievements table. That's what this refers to. We have a User who should be associated with the achievements table. So it sounds like we need to set up a relationship table, a pivot table.

We have a User who should be associated with the achievements table. So it sounds like we need to set up a relationship table, a pivot table. And you'll remember in the first episode, we worked that out. So if we scroll down, yeah, here we decided, yeah, we need some kind of intermediate table so that we can record the user_id as well as the id of the achievement that they unlocked or they were awarded. We're still figuring out the terms. So let's take care of that. I'm going to make a new migration here called create_user_achievements_table. And the table name is user_achievements.

I'm going to make a new migration here called create_user_achievements_table. And the table name is user_achievements. All right, so that'll give us this file here. And again, we decided that we need an unsigned integer. Always go with unsigned if you have something that will be positive, like a user_id. And then we also have one for the achievement. Now for the primary key, we could either make it based on the user_id and the achievement_id. Some people do that. Some people don't.

Some people do that. Some people don't. If you don't, you could still say table unique and make sure that you can have only one occurrence of this combination here. Let's do this. Let's say primary will be the user ID and achievement ID. Here they make the primary key. Okay, so let's switch back to our Achievement model now. And we should be able to say, all right, this users attach user. And we'll set up that relationship.

Defining Many-to-Many Relations5:02

And we should be able to say, all right, this users attach user. And we'll set up that relationship. So what is the relationship here? An Achievement can be applied to many users and a User can be applied to many Achievements. So we want a belongsToMany relationship there. And we'll return that and fix that. Okay, let's run our test again. So it's failing now because Laravel is trying to use a convention for the pivot table. And that will be the singular form of both tables in alphabetical order. So if we have an achievements table and a users table, that becomes a pivot table name.

And that will be the singular form of both tables in alphabetical order. So if we have an achievements table and a users table, that becomes a pivot table name of achievement_user. We didn't use that approach. So instead, I'm going to hard code that, userAchievements, and run it again. But now it's still failing. And that's because we had the relationship on this end. And in fact, if you want to see a quick example of the query, let's listen for a SQL query, and I will var_dump that. So if we give that a run, here we go, insert into the user_achievements table with these

and I will var_dump that. So if we give that a run, here we go, insert into the user_achievements table with these two values. So that is correct. So at this point, we can go back to our FeatureTest. And we can see right here, that relationship does not yet exist. And right down here at the bottom, we'll add that. So what is the relationship between a User and their achievements? Exact same thing. belongsToMany.

Exact same thing. Belongs to many. And we'll return that. So if we give that a run, now we get green. It's working. So let's go back to our feature test. And let's die and dump the $user's achievements. And here we go. So we can see the $user has earned this achievement here. But if we had not done that, give it another run, we get an empty collection.

So we can see the User has earned this achievement here. But if we had not done that, give it another run, we get an empty collection. Okay. So let's bring that all back. Take a look at things. Oh, you know what? We do need to be using php artisan migrate:refresh. I must have deleted that by accident. Given we have a User and we have a Badge, if that Badge is awarded to a User, then the User should have exactly one Badge.

Finalizing Assertions7:09

Given we have a User and we have a Badge, if that Badge is awarded to a User, then the User should have exactly one Badge. So we'll say this assertTrue. And we'll say the User achievements, give me the first one. That needs to be that achievement that we whipped up earlier. We could also just do an assertEquals on the ID of both. But let's give that a run. And we do get green. All right. So that'll do it for this episode.

Recap and Next Steps7:32

All right. So that'll do it for this episode. Let's think once again everything we've done so far in this series. We've written a general outside-in feature test that when a User earns the necessary experience, they should be awarded a Badge. In the second episode, we decided, all right, well, when a User is granted experiencePoints, it sounds like we need to fire an event. We need to broadcast an event so that we can hook in and check, do we need to apply a Badge to the User given these new points that they have earned? Then in the third episode, we use TDD to build up the migration and the attributes for an

to the User given these new points that they have earned? Then in the third episode, we use TDD to build up the migration and the attributes for an Achievement. And then finally, in this episode, we built the relationship between a User and the Achievements. So now, using this API, we can award any achievement badge to any User. In the next episode, we're going to switch back to our very first test, and we'll get this to green.

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