4.1 Displaying Users and Managing Roles
To create an interface for managing users, we'll rely upon the same CRUD-type operations we used when writing our page management system. Let's apply those same techniques to managing users' roles.
1.Introduction1 lesson, 01:23
2.Getting Started4 lessons, 45:12
3.Managing Pages6 lessons, 1:12:31
4.User Management2 lessons, 27:40
5.Managing the Blog3 lessons, 42:25
6.Adding Extras2 lessons, 25:48
7.Implementing the Front-End3 lessons, 32:10
8.Homework Review1 lesson, 07:11
9.Conclusion1 lesson, 01:24
4.1 Displaying Users and Managing Roles
Implementing our user management is going to be very straightforward because all of the concepts that we have talked about can be applied to managing users as well. The only difference is the data that we are working with. So let's go ahead and start by creating our controller. This will be a resource controller, and let's just call it users controller or admin/users controller. This will be a resource, and let's specify the model as well, as user. So there we go, let's open that up and let's start working with it. So users controller, there it is. Now one thing that we didn't do with our PagesController, and we probably should, is get rid of the actions that we aren't doing anything with. Like for example, in our PagesController, we're not doing anything with our show method. I mean, we do something with everything else but the show is not used. So whenever we set up our routes, we could specify that we want everything except our show route. So let's go ahead and do that, we'll go to routes > web.php. And whenever you call the resource method, we pass in our URL, we pass in the controller, and then we can pass in the actions that we want to include, or the actions that we want to exclude. And that's what we are going to do is exclude this. So we say except, and then except is going to be an array of all of the actions that we want to exclude. So in this case, it's going to be simply show, and that's going to be fine. So we could go ahead and delete that show method inside of our controller, and that makes our controller a little cleaner. So let's think about this as far as our users are concerned. Now we definitely want the index because that's going to display all of our users. We can create and store, we could make the argument that we want that, but we already have that functionality built into our application. We can register a user, and then we have a user to actually work with. So let's get rid of those as well. And we will do the same thing for show. We don't really need to show anything. We do however need to edit and update, and probably destroy as well. So let's go ahead and setup the routes for our users controller. Let's just take what we have for pages, use that as a basis. The URL is going to be admin/users. The controller is, of course, our user's controller. And then as far as the exclusions are concerned, yes, we want to exclude show but we also want to exclude create and store as well. So there we go there. Let's make sure that's saved and then we close it. And all we need to do is just start implementing this. So as far as our index is concerned, that is going to display all of our users. So we will return a view, it will be called admin.users.index and then of the data that we want to pass to it. So we could, now let's use the width method, that's a little bit cleaner since we are just passing in our model of users. So we'll say model, and then User:all, that will give us all of our users. So let's go ahead and implement that view, so we will go to resources > views, let's, you know what? Let's take our pages, I'm going to be completely lazy and we're going to use our pages as a basis. I mean we might as well because the same ideas are going be used here. So we're going to call this users and of course our model is going to be a little bit different. So we're still going to have our table but our columns will be different. Let's have the Name as well as, I guess the Email address. And we can also go ahead and list all of the roles that user has, so let's just say that, Roles. And we're still going to use this for each loop but let's change the variable names so that it makes sense here. So we will have our model as $user, and we will have our link in that first column. The route, however, is going to be users.edit, we'll say that the user is the user id, and then we need to change the text here. So we will say user and name. And for our second column, you'll say user and email and I don't think there's anything else. We can get rid of this create New link. So let's do that. And let's just see what this looks like. So let's go refresh, although let's go ahead and change our link here because we just left that as a hash. So let's, first of all, php artisan serve. Then let's go into our template so that we can change the href of that anchor. So that is in layouts, app.blade.php, and manage users, so we're going to specify our route here. Let's just copy one that we have, paste that in and the route is going to be users and index. So that link is going to be good, so let's refresh. Let's click on it, and we have our users, Admin and Joe, and now we just need to add our roles. And all we need are the names of our roles. We don't need anything else because this is just for informational purposes. So that as we are viewing the list of users, we can see that, hey, Joe's an author, let's make him an editor. Now here's the thing about our roles. Right now we have two users, and they are assigned a single role each. The way that our system is set up, we can assign as many roles to a single user as we want. So we need to take that into account whenever we display the roles. So display them as a comma separated list of names makes sense. So let's do that. Let's add the atd element, and we're going to use the implode method, not method, the implode function, because that's what we have it for, so that we can create a string out of an array. Now here's the thing though, we have to pass in an array of our role names to implode so that we generate the correct string. But we can easily do that like this. We can say user, we can use our roles method and then we will get those roles. Now this is going to return a collection of objects, and we want to get just the name of our roles. And we can do that with the collections method, simply called pluck. This is going to allow us to pluck the value of a given key, our key is name. So this is going to pluck all of the names, but this is going to return a collection as well. And if we pass a collection to implode, we will get an error. But we can turn a collection into a pure PHP array by calling the two array method. So if we go back, let's refresh, we're going to see our roles. Now of course, since we only have one role, we just see one role per user. But as we edit our users and manipulate the roles that they have, then we will see this change to be a comma separated list. So let's click on Admin. It doesn't really matter, but now we want our edit form. So let's go to our controller, and we want to return a view. We'll call this admin.users.edit. And we will also pass in a model for the given user. And once again we're going to use the width method. I like using the with method whenever we just have one thing to pass to the view. It just make sense to do that. I know that we didn't do that in the pages but we also used our PagesController as our learning controller. So let's see, we should have an edit view because all we did is copy and paste our views. So let's find users, let's find edit. We do need to modify here. Now, as far as the edit page title, let's do this, let's say edit and then we will use our model name in order to display the name of the user. And we also need to update our action, so our route is going to be admin, not admin users update, and the data will be user, and then the model ID that will be fine. And we don't need a partial view since we have just one form that is our edit form, we are going to not use a partial view. So let's grab the contents of that partial view or at least some of it at least, and we will use that as a basis. Now the idea that I have in my head is to just display the rows for the user. We wont edit the name or the email address, although in a real world application we will do that but we know how to do that. Let's do something a little bit different with some check boxes. So in this case, we could make the argument that we don't really need any of the error messages because we could remove all the roles from the user. So in that case we won't have any errors. So let's get rid of the error messages. And then we just need to modify our forms so that we just display all of the roles as check boxes. But here's the thing, we don't have our roles here. What we do for the user, we know what roles have been applied to the user but we don't have all of the roles from the database because we want to list those. So my choice of using the with method isn't really the best here because we need to pass more than just the user, we also need to get the roles as well. In that case, we need to pass in our data as an array so that we will have our model, which is of course going to be our user. So that's going to stay the same. But then we will have our roles. And we can just say, role all, although we probably need to add a use statement for roles. So let's go ahead and do that. We have user, we now have role, and there we go. Let's get rid of the width method there, but everything else should be fine. So now that we have our roles, we need to iterate over our roles in order to display them as individual check boxes. So we will get rid of pretty much most everything here. We'll leave the submit and we'll keep this div element here because we're going to use that as a basis. So we want to our for each loop and we're going to iterate over our roles, we'll just call each one role. And then let's go ahead and add in the endforeach before I forget to do that, and let's change the class of this div element. We're going to change this to simply check box because that is typically what's used for bootstrap. We are going to use the label, but we're going to wrap the input element with the label. So let's do that. And we'll also have the role text here, so after the input element, we will say role, name. And then as far as the input element itself, this is of course going to be a check box. So let's change the type to check box, we don't really need the class here because all of the styling is going to be supplied through the div class check box. And we don't really need the ID as well, so let's get rid of that. But the name, this is gonna be an array, essentially of roles so we're gonna say roll or roles I guess, and then have our square brackets. The value is gonna be the ID of the roll so let's do that. But we also want to check the check box if the user already has that role. So we can do that like this. We could use our model, it has that hasRole method. We could pass in the role name, and if that's true, then we will output the checked value, otherwise it would be just an empty string. So that should be fine. Let's refresh and see what we have, there we have our Edit Admin form. But something else that comes to mind, we are logged in as admin. And you can make the argument that we don't want the currently logged in user to be able to edit their own user. That could be dangerous, because they uncheck admin, well then they are screwed. So [LAUGH] I mean we could add protections in for that but the easiest thing to do would be to just simply say nope, you can't edit yourself. So let's go ahead and let's add that check. So let's do this for both the edit and the update methods. And it's going to be as simple as this, we'll say off user and we'll use the ID is equal to the provided user id, then, let's just redirect back to the list. And it would be nice if we had a status in our list so that we could supply a status. And we might do that in the next lesson, just to add a little bit of polish here and there. So let's return redirect and of course that is going to be our route which is called users.index. Well let's copy and paste that into the update method because we need to do that same check if a request is made for updating a user. And then we just need to update that user. So we'll do that like this. We'll say user, we'll get its roles and then we'll call sync. And this is how it works, we pass in an array of the ID's of the roles we want to then apply to this user. So if we wanted to make the user an admin and an author, we would pass in the IDs of 1 and 2, and everything else would be removed, and those would be the roles that the user has. So we can get an array of our values simply by using our request and then roles, and that's going to be fine. But after we add those roles or modify the roles, we need to return back to the index. So let's just do that. And before we test this out, let's make sure that we use off and we should be good to go. So let's go to the browser, let's refresh. We have our, well, okay. Well, okay. It redirected us to admin. I was expecting to see the form but of course we wrote the code to redirect us and so that works, that's great. So let's try to edit Joe, Joe is an author, and let's make him an editor as well. So whenever we submit, the page has expired due to, how is that possible? We just loaded that. So let's refresh, let's try that again. Okay, so there's something wrong, let's look at our edit. And you know what that CSRF is not there, I did not copy that, so that's easy enough to do. We need to just copy and paste that, and now everything should work. So let's refresh, let's click on Editor, we Submit, and voila. We have now edited the permissions that Joe has, and we can of course incorporate all of our existing roles, which is kind of pointless because if you're an admin, you can do everything. But at least we can see that it works. So let's just make him an editor and an author. And in the next lesson we will finish up the users controller. We need to protect it first of all which we have already done for the most part. But there's one other step that we need to do to ensure that only admins have access to that. But then we can also add little bits of polish here in there, like the status message that I mentioned. And we will do all of hat in the next lesson.