3.4 Storing and Updating Pages
With the views written, now we can actually store and update our pages in the database. Let's write that code!
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
3.4 Storing and Updating Pages
In the previous lesson, we set up the views for creating and editing our pages. Now we need to actually perform that work, so whenever we click on the Create new link, we of course are taken to the Create new form. And whenever we submit that form, the store method on our PagesController is going to execute. So that's where we want to get the data from the request and store that within our database. So the first thing we want to do is get the user that is currently logged in. Because if we are going to associate this page with the user, we need to get that user. So we need to add a use statement up here and we're going to use of. Now of course, the user needs to be logged in, that's very important. And eventually, we will get there, whenever we start implementing the security, then that's going to be okay. But for right now, just make sure that you're logged in, otherwise you're going to have some issues. And here's what we're going to do, we're going to say Auth and then we're going to use the user method to get the currently logged in user. And then we are essentially going to do what we did by seeding our database. We are going to get our pages and then we're going to call the save method and we are going to pass in the data that we want. Now here's how we are going to do that, we are going to use our request, all of the data that is coming from the user is in this request object. And we could say, okay we will take all of the data coming from the user and we will save that, that is very, very, very dangerous. Because the user could be including extra information. Because there's nothing stopping anybody from coming to the inspector, adding form fields and then submitting the form, nothing gonna stop them there. So what we want to do then is we only want the data that we are expecting. That is the title, the URL, and the content, so we're going to say request only, we want only the title, the URL, and the content, and that is going to do just that. So let's break this up so that it's a little bit easier to read, we'll put our array there on another line, and that's going to be okay for right now until we actually try to do it. So let's refresh the page and let's just call this My First Test and we'll have the URL of test, and this is my content. So whenever we submit this, we get an error, fatal throwable error, Argument 1 passed to, blah, blah, blah, save() must be an instance of blah, blah, blah. So okay, we can do that, we can new Page, we'll pass in that data, and we will try that again. So let's go back, let's refresh, my First Test, /test, Content goes here, we submit, what do we get now? Another error, MassAssignmentException, so what this means is that we are taking data from the user, and we are trying to essentially mass assign the properties on our page object with the data that's coming from the user. Now this is not an issue with Laravel, not an issue with PHP, this is an issue with any technology framework language that has implemented something like this. To where we can take just an object which is essentially what we have with this request and we're saying, okay, just mass assign these properties. And then they get mass assigned, and as long as you're careful, it's not that big of a deal. But if you're not careful, then things could get assigned that you don't want to be assigned like sensitive things like passwords and things like that. So what Laravel does is it protects us from this by default. There are some platforms that don't, you're just, you're stuck. You have to be sure that you do exactly what you need to do, Laravel takes a good approach, in my opinion. They protect us by default, we have to opt in to say that it's okay to mass assign these particular properties, title, URL and content. We might want to limit some of that, if it was highly sensitive data like passwords or things like that. But in this case, title URL and content is fine, so what we end up doing then is saying that it's okay to mass assign title URL and content. And so to do that, we go to our page model and we're going to add a protected property called fillable, and this is an array. And each item in the array is going to be the name of the property or attribute that is okay to mass assign, so that is title URL content, there we go. So if we go back, let's refresh the page, the reason why I'm going back and refreshing is so that the token is refreshed and so everything's going to match up. So once again, My First Test, URL is going to be /test, content is Content goes here, so now whenever we submit this, it's going to save it. Well we don't see anything on the page, the reason being because the code did exactly what we told it to. It saved our page but then it didn't do anything else, it didn't return a view, it didn't redirect anywhere, it just did nothing. So what we want to do after we save it, is return back to our index, so we will return, we'll call redirect. Now, before we redirected to home whenever we did the middleware, if we look at AccessAdmin, we just redirect it to home. Well that is an actual URL, which we could do inside of our PagesController. But we have our named routes, and they are there for a reason. So instead we'll call redirect, but we are going to call a method on this and we are going to say route. And then we will specify our route name which is pages.index. And so now, if we go back, let's go to our form, let's refresh. And we'll say test again, and then our URL will be /test-again content doesn't matter. And we will click submit, and we are once again, well not once again, we are now redirected back to our index. But notice that we now have our new pages, so great, now let's write the code for editing. Editing is going to be very similar, actually, we have the data already or at least we have our object page. So what we're going to do is we're going to fill our existing object with the data that is coming from the request. I'm just gonna copy and paste because that is going to be easier, so we'll just copy that, we'll paste that and then we will save our page. So we'll say $page save, but once again, we want to do the same thing, we want to redirect back to something. We could redirect back to our edit form, but typically, whenever we are done editing a page, it make sense to go back to the index once again so that if we wanted to edit another page then we could do that. Same exact code so let's just copy and paste that again, and there we go. So let's test that out, let's test My First Test, and we'll just add edits and for the URL, let's change it to edited and then content goes here. I just wanna make sure if it's going to edit anything, so let's add something a little bit different, we'll say Edit content there, so we'll submit. We did not get an error but notice that the title did indeed change. If we go back in, the url changed and the content changed. So we have creating, we have editing, and that's a really really wonderful thing. However, the very first rule of accepting user input is to not trust user input. So we need to validate this data, and we can do that by creating our own form request. So let's do that. Let's go to the command line, let's stop artisan from serving this and we are going to say PHP artisan make:request and then we need name this. Now typically we have a single request object for a single request, so we would have like a StorePage, for the store method and then we would have UpdatePage. But we have the same exact information, and really, we're going to have the same exact validation rules for both of those. So let's call this something other than those two things, we'll say WorkwithPage maybe. One of the hardest things in programming is naming things and that is exceptionally true with me. So this might not be the best word but it's going to work. So this created a new file inside of app, http, Requests. And here we have WorkWithPage, and we have two methods, we have authorize and then we have rules. Now the authorize method is very useful because we can write code inside of this method. That would determine whether or not this request can be performed by the user. Right now, we're just going to make that true. And then as far as the rules are concerned, we can specify if any of the fields or the attributes are required, if they have a max link or things like that. So we have title and we are going to say that the title has to be required. In fact, we are going to say that for everything, so we'll say title URL is required and we will also say the same thing with content, there's really no use in having a page if we don't have these three things. Now there are many different validators that we could use, and if we wanted to we could add other validators by using a pipe, and then whatever validator we wanted to use. So if we wanted to have a max character length of 10, for whatever reason on the contents, yeah, that's what our validator would look like. It would have required, and then the pipe and then max:10, but let's just stick with required. So now, what we need to do is go back to our PagesControllerr, and instead of type hinting the request here, we're going to type hint our work with page. And we will do the same thing for our update method, and Laravel is going to automatically perform that validation for us. We don't have to worry about that whatsoever, so let's go to the command line, let's run PHP artisan serve so that we have that running. Let's go to the browser, let's refresh the page here, hopefully we are still logged in, we are. Let's create a new page and we'll say test with validator, we'll first have a test that's going to pass everything. So test with validator, hopefully this works, and we will see, of course not because I didn't add the use statement, duh. Okay, so use app http requests, and then WorkWithPage, it's the important things that you always forget. [LAUGH] So we'll say Test With Validator, and what was this Test With Validator? Hopefully this works, and after we submit, we see our new page in the list. Now let's go back to our create form and let's submit this without entering any data. Because we know that these are required, we know that this was an invalid request. And notice that it didn't take us back to index. Instead, it just reloaded the page. So what we want to do is display some messages. And thankfully, whenever you use a request object and you are validating your model, there are error messages that you can display. And it's automatically passed to our view as a variable called errors, so let's do this inside a field, so that we don't have to Go to the create, or edit views. And we are going to check to see if we have any error messages, so let's say @if and !$errors isEmpty. Then we have some error messages that we want to display. So we are going to start with a div element that has a class of alert and alert-danger. That way, the user can immediately see that something is wrong, so that is good. And then we want to loop over all of our errors and display them. Now we do that like this, let's have a @foreach, or before we do that, let's have a UL element. And then inside of the UL element, we'll have our @foreach, and we're going to say errors-all. We're going to get all of our errors as and let's just call that message, and then we will display the message in an li element. So @endforeach and then li, we will output the message, so whenever we go back to the browser, let's resubmit. And we see our error messages. The title field is required and so on and so forth, these are the default error messages but we can override them if we want to. We need to do that inside of our work with page class, so we're going to override a method called messages. This is going to return an array where the keys are the name of the field and the validator. So we would say title.required and then we will specify whatever we want this to be. You must enter a title, now this isn't going to change any of the other messages just for the required title. So if we go back and refresh, well not really refresh, if we resubmit we can see that the message for our title field changed to what we specified. But the other fields are using the default message, so we can come back. And in this case, let's just Please enter some content, so there you go. So if we go back, we submit, and we see our custom error messages. So we now have a working PagesController. We are reading the data, displaying the index, we are creating, and we are editing. In the next lesson, we're going to talk about security because in the case of working with our pages, it's not good enough to just protect our controller. We also want some granularity based upon our roles and we will look at that in the next lesson.