This episode is for members only

Sign up to access "Laravel Teams" right now.

Get started
Already a member? Sign in to continue
Playing
38. Creating new teams

Episodes

0%
Your progress
  • Total: 4h 36m
  • Played: 0m
  • Remaining: 4h 36m
Join or sign in to track your progress
01. Introduction and demo
4m 49s
0%
02. Setup with Pest
4m 2s
0%
03. Building the user teams relations
6m 5s
0%
04. Creating a personal team when registering
6m 3s
0%
05. Leaving all teams when an account is deleted
3m 55s
0%
06. Tracking the current team
4m 50s
0%
07. Showing team details in the UI
2m 55s
0%
08. Switching to another team
7m 24s
0%
09. Authorising team switching
6m 53s
0%
10. Updating a team name
10m 48s
0%
11. Basic roles and permissions setup
5m 26s
0%
12. Team roles and permissions middleware
9m 18s
0%
13. Authorising current team updates
3m 43s
0%
14. Testing team permissions through HTTP requests
3m 58s
0%
15. Leaving a team
10m 50s
0%
16. Displaying team members
8m 42s
0%
17. Making team members look better
5m 3s
0%
18. Removing a team member
15m 18s
0%
19. Preventing self removal from a team
4m 7s
0%
20. Storing invitations
13m 31s
0%
21. Validating invitations
6m 38s
0%
22. Authorising team invitation creation
6m 22s
0%
23. Displaying invitations
3m 16s
0%
24. Revoking invitations
12m 46s
0%
25. Sending an invitation email
13m 6s
0%
26. Accepting an invitation
12m 22s
0%
27. Displaying a modal to change a member’s role
10m 31s
0%
28. Updating a member’s role
9m 5s
0%
29. More authorisation and checks for role changing
10m 14s
0%
30. Fixing up the email sending test details
49s
0%
31. Fixing and validating email addresses for invites
1m 32s
0%
32. Tidying up @can directive checks
3m 25s
0%
33. Detaching roles when removing users
5m
0%
34. Adding an extra layer of protection to the team middleware
6m 35s
0%
35. Getting related models through teams
5m 37s
0%
36. Building a helper to access the current team
10m 47s
0%
37. Getting all related models through all teams
7m 15s
0%
38. Creating new teams
13m 7s
0%

Transcript

00:00
Okay, let's focus on creating a new team. Now this might seem pretty straightforward, but a good thing about this is over in our User Observer, we're pretty much already creating a team here,
00:12
associating the team with the user, and then going ahead and assigning roles here. So this will be interesting and it'll mean that we can pretty much just take all of this
00:22
and maybe move it to some action class that we can reuse in both places. So it's a good exercise in doing this and then going ahead and of course running our tests,
00:33
seeing what happens. Now, just before we do start work on this, let's go ahead and run all of our tests just to make sure everything looks good.
00:40
We do have a failure here, so let's have a look over in the Team Invite Controller Test and I think it's this can accept an invite. I think what we've got here is an issue
00:51
where the team invite has not been created and I have a feeling we just need to make sure we're putting the fresh user out of the database before we go ahead and do this.
01:03
So let's make sure that's fixed up before we get started and that's all good. So once we do some refactoring, we'll know if everything still passes.
01:13
Okay, so let's work on the really basic boring stuff first of all. So let's come over to our Team Controller and let's create out two methods here.
01:22
The first one is gonna be a create method. That's just gonna be to show the form to actually create the team and then we're gonna have a store on this team as well.
01:32
So for create, let's go ahead and return a view in here and let's put that in the team directory and call that create and we can go ahead and make that out on the command line
01:42
with make view and team create. Okay, so let's go and just grab our dashboard, copy that over to that create.blade.php file and let's get rid of some of the stuff that we have in here
01:57
just to keep this super simple. So let's just get rid of all of this here and put form and let's call this create team. Now we've got that view,
02:08
let's go over to our web routes and create out a new route for this. So we can do this pretty much anywhere. Let's do this first up here.
02:16
We're gonna say get team slash create and we're gonna head over to the create method for that. Of course, call that team create and then we're gonna have a post route to team.
02:26
Now, the way that we've named this is team, a singular. Usually what we would do when we have a resourceful controller like this is we would give it a plural name.
02:36
Just bear that in mind, of course, you can go ahead and change that if you want to, but we're gonna move that over to store and say team.store.
02:42
So we've got the team create route, let's head over to our navigation and let's find out where we have this team settings dropdown link
02:50
and I'm going to create out a new create team link in here and of course, hook that up to team and create. So if we head over now, we should be able to click on create team
03:01
and go through to this page, which will show us a form. So let's start to build this out. Again, this is the real basic stuff, but then we'll get to look at refactoring
03:10
the actual process of doing this. So let's get rid of this just inside of here and why don't we just head over to any of our pages. Let's just say login and we'll just grab
03:21
sort of any of the fields in here that we want to steal. So let's grab the email address, pop that over into a form inside of here and then we'll have a button in here as well.
03:33
We'll just change over the text and stuff in here that we need. So let's create a div in here, get rid of this margin
03:43
and we'll give this a margin top of four. Let's call this create team or label it create team. This is gonna be for the team name.
03:52
We'll give this a label of team name. Same thing for this as well. It's gonna be called name. Type will be text, name will be name.
04:01
The old value that we pulled through in case of any validation will be name. We don't care about auto-completion and let's get rid of the required field in here
04:10
or attribute in here as well. And of course you can keep that in there if you want to. Okay, so let's go ahead and give this a method of post. Let's bring in our cross-site request forgery protection,
04:20
all the basic stuff and let's hook this up to that team store route. So let's hook that up there. Okay, so we should now have something that looks like this.
04:30
I can go ahead and enter something, hit this through and that will go through that route to actually create the team out. So really all this have to do
04:38
is just head over to our team controller and just start to fill in this store method. So what do we need to do here? Well, the first thing is we wanna go ahead
04:46
and validate this, pretty important. Then we want to create the team, which we already have the functionality for. So we can go ahead and borrow that
04:54
and then refactor this down into a single class a little bit later. Then we want to go ahead and redirect back. Now, sort of in between this, as well as creating the team,
05:05
we wanna associate it with the user. We want to set the current users team as the team we have created. All of this stuff, which we've already done
05:18
over in the user observer. So we pretty much just wanna do everything that we do when we create a user. So that gives us a clue
05:28
that we can refactor that functionality. Let's work on the validation first of all. So to do this, we're just gonna create out a form request. So let's go ahead and make our request here
05:38
called team store request. Let's pull this into here. So team store request. We will be writing a basic test for this as well,
05:46
but we won't be covering validation in our tests. We can do that very easily. And the rules here for the name, again, we'll just keep this pretty straightforward.
05:55
Required a max of 255. Of course, you can bump that down as well if you want to. So validation is working. Let's redirect back and let's just try this out.
06:06
There we go. Validation is working. And if I type something in, sure enough, we're all good. So all that's left to do is figure out
06:14
how we can basically take all of this functionality from our user observer and just reuse it. For this, I tend to create small action classes. Once things get more complex in the future,
06:28
we can come up with different ways of doing things. But for now, at least this is so simple that it just requires a simple class. So let's create out a directory called actions
06:39
inside of our root directory. And let's create out a plain PHP class in here. There are packages that allow you to deal with this, and we've covered this before,
06:48
but let's just call this create team. Just keep this super simple for now. And in here, let's not even interface this. Let's just give this a handle method.
06:58
Now, what do we need to create a team? Well, we need to know the user who we're creating the team for. So if we just go over to our user observer,
07:06
we know that we need the user in the context of this so we can attach it to the user's list of teams and associate it with their current team. And we also need a bunch of data
07:14
to create the team, like the name. Now, when we did that in our user observer, that was really simple because we could just take the user's name,
07:22
but now we're working with a form. So we need to allow this to be passed in. So let's first of all pass in the user that we want to create this team for,
07:30
and then we'll pass a basic array of data that we want to use to fill this in. So bear in mind at the moment, all of our tests pass,
07:38
and a lot of these tests are dependent on this initial team for this user and the user observer getting created. So what we can pretty much do
07:47
is we can take all of this functionality, move it over to that action that we're just creating, invoke the action in here, and as long as our tests pass,
07:56
we pretty much know that this was a successful refactor and that we can reuse this functionality. So I'm going to paste this entire lot in, and let's think about what we need to change here.
08:06
So name is going to be slightly different. That's now going to take in all of the data that we need to create that team for, and this will associate it
08:14
with the team that's just been created. That's all good, and this is all good as well. So this should just work now. So how do we use this inside of our observer?
08:24
Well, we can go ahead and create a constructor in our observer, and we can pull this in. So let's say create team, and we're going to name this create team.
08:33
So we don't need to do anything within our constructor, but we now have this as a protected property. What we can now do is say this create team handle, we can pass through the user,
08:43
which is the user who's just been created, and we can pass through that bunch of data that we originally had directly within the observer. That's the name of the team,
08:51
which we know is just the user's name once they get created, and that should do the exact same thing. So we've just basically moved this
08:59
from one place to another. Let's go ahead and run our tests and see what we get, and yeah, everything passes. So we're pretty confident that this is now working nicely.
09:08
Now that we've done that, over in our team controller, when we create a new team, this is incredibly simple.
09:15
We can go ahead and either pull this into the constructor of this entire controller, or we can pull the create team action that we've just created directly into this method,
09:25
and then we can just say create team handle. Now, who's the user that we're creating this for? Well, it's the currently authenticated user. And what data are we passing through to?
09:34
It's just the validated data that we have. So let's go ahead and pass in request validated. That should be everything that we need to do now to create a new team,
09:43
associate it as the current team that we're in, and also assign us as an admin of that team. Let's try this out over in the UI, and then we'll create a really quick test for this.
09:54
Okay, let's call this code course again, and let's go ahead and click create team, and there we go. Sure enough, we have obviously created a new team.
10:04
We switched over to that team, and if we go over to the team settings for here, we are a team admin. So we're just doing everything
10:11
that we would normally do when we sign up. Okay, let's go ahead and write a quick test for this. So we've got a team controller test, like a general controller test for this.
10:21
So we'll just put this in here. Of course, you can write tests for validation if you want, but I'm just gonna do one for the successful. It can create a team.
10:30
Okay, so how do we test for this? Well, we need a user. So let's go ahead and use our user factory and create this out,
10:38
and let's go ahead and act as that user and just send a request directly down to here. So let's say acting as this user, we're gonna make a post request to,
10:48
and again, we'll use our root helper, team and store, and we need to pass a name down for the team that we want to create. Let's assign that at the same time so we can use this.
10:58
So let's say a new team, and let's assert that we are redirected or assert that this is okay, whatever you want to do.
11:06
Okay, let's go ahead and just run this test in isolation. So let's say test and filter can create a team. That looks good, so we know that at least we get redirected back.
11:17
But now what do we want to expect here? Well, we can look at the database level, or we could just start to plot this data directly out of the relationships.
11:25
Because we are, as part of that action, adding stuff to this user, we're gonna go ahead and make sure that we grab a fresh instance of that user
11:33
plus the relationships out of the database. And let's expect that the users teams, so the teams that they have to have count of two, because remember,
11:43
they should have already had a team created here when we created them, they should now have two teams. So let's go ahead and run that,
11:50
and yeah, that works. What else might we want to do? Well, we might also want to say, well, the first team's name is equal to, or to be,
12:02
and then use that name in there. Now, it's not actually first, it's gonna be last, because it's the latest created one.
12:08
Let's go ahead and run that, make sure that that works. And what could we also do here? Well, we could expect that the user's current team,
12:18
and we could say name or ID, so we could do current team ID, to be, in fact, we're not gonna know the ID, are we? So let's just use the name here, to be name.
12:28
So basically, have we been switched over to that team? And again, you can use the current underscore team, underscore ID, if you actually had the instance of the team, but we don't.
12:39
Okay, there we go. So we've got four assertions on that. We're pretty confident at this point, that that will create a team for us
12:46
in exactly the same way that the user observer does. Now we've got this little refactor in here, which means that this functionality is nicely tucked away in its own action.
12:57
And if anything about this changes, we know that the same thing will happen for when a user is created, for when they go ahead and also use the create team form.
38 episodes4 hrs 36 mins

Overview

Need team functionality in your Laravel application? Let’s build it from scratch.

We’ll cover the basics of creating teams, switching between them, sending secure team invites by email, and managing team members.

Powering everything will be roles and permissions for each member, with the ability to switch roles directly from your team dashboard.

Once you’re done, you’ll have mastered team functionality in Laravel.

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

Episode discussion

No comments, yet. Be the first!