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, 46:41
3.Managing Pages6 lessons, 1:12:31
4.User Management2 lessons, 27:37
5.Managing the Blog4 lessons, 41:51
6.Adding Extras2 lessons, 26:07
7.Implementing the Front-End3 lessons, 30:24
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\UsersController. 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 to working with it. So users controller, there it is. Now, one thing that we didn't do with our pages controller, and we probably should is get rid of the actions that we aren't doing anything with. Like, for example, in our pages controller, 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 to 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're going to do is exclude this. So we say accept, and then accept 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 index, because that's going to display all of our users. We can create and store. We could make the argument that we want to 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'll 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 set up 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 users 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 save and 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 the data that we want to pass to it. So we could, 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 us go ahead and implement that view. So we will go to resources views. Let's, you know what? Let us take our pages. I'm going to be completely lazy, and we are going to use our pages as a basis. I mean, we might as well because the same ideas are going to 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 are 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 could also go ahead and list all of the rows, that user has. So let's just say that roles. And we are 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 then 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, we'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 this manage users. So we are 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 purpose. 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 a TD element. And we're gonna use the implode 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 collection's 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 toArray 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. 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 width method, whenever we just have a one thing to pass to the view. It just makes sense to do that. I know that we didn't do that in the pages, but we also used our pages controller 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, non-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're 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'll use that as a basis. Now, the idea that I have in my head is to just display the roles for the user. We won't edit the name or the email address. Although, in a real world application, we would 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 of the roles from a 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 form, so that we just display all of the roles as checkboxes. But here's the thing, we don't have our roles here. Well, 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 width 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 elements here because we're going to use that as a basis. So we went to our foreach 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 checkbox, 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 a 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 checkbox. So let's change the type to checkbox. We don't really need the class here, because all of the styling is going to be supplied through the div class checkbox. And we don't really need the ID as well, so let's get rid of that. But the name, this is going to be an array essentially of roles. So we're going to say role or roles, I guess, and then have our square brackets. The value is going to be the id of the role, so let's do that. But we also want to check the checkbox 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 can pass in the role name. And if that's true, then we will output the checked value otherwise, so 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 you know 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 if they uncheck admin, well, then they're screwed. So, 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 wouldn't 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 add a little bit of polish here in 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 will get its role, and then we'll call sync. And this is how it works. We pass in an array of the IDs of the roles that 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, 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. 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. 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 we have now edited the permissions that Joe has. And we can of course, incorporate to 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 and there, like the status message that I mentioned. And we will do all of that in the next lesson.