Project Overview and Goal 0:00So let's define the target viewer for this lesson. Maybe you've just begun learning about Laravel, you've done a little research, you've reviewed the documentation, maybe you've read a couple articles, you went over our Laravel setup for noobs video where you learned how to install it, and mostly you've just kind of toyed around. So now at this point what you really need is your first little project. And these are the points where you build a little task app or a blog, those little starter projects that help you learn the framework. That's what we're going to do in this video. Let's build a little to-do list for your family, and this way we can assign specific tasks to individual members of your family. And that way at any given point we can review which tasks have been assigned to John or Susie or Tim. You get the basic idea. So let's get started. Now we're going to begin with a new installation of Defining Routes and URIs 0:41at any given point we can review which tasks have been assigned to John or Susie or Tim. You get the basic idea. So let's get started. Now we're going to begin with a new installation of Laravel. I'm going to assume that you've already learned how to do that and have watched this lesson. That means if I open up my sidebar the dependencies have been installed and we are ready to go. I will begin by editing my routes file. And here's where we can essentially define how we respond to specific URIs. So for example, what if you want somebody to go to yoursite.com slash tasks. Well in this case that should return all tasks, whether they belong to you or your wife or your child. But then maybe we also want to do something like yoursite.com slash john slash tasks. And in this case that will only display tasks that are associated with John. Well, a routes file is where we can set this up. Let's do this first one to begin. I will say routetasks. And in this case that will only display tasks that are associated with John. Well, a routes file is where we can set this up. Let's do this first one to begin. I will say route when the user makes a GET request to tasks, then what do we want to do? Well, we have a couple choices. We could pass a closure here like so and we could return a view, something like that. Or if we want to reference a controller, which is more likely in your day-to-day work, we can specify a controller method. Let's do that now. We will call it tasks controller and we will call a method called index. All right, let's see if that works, but it won't quite just yet. But let's go ahead and view it in the browser. We can boot up a server by doing php artisan serve. And if you do need to override the default port, you could do that right here. So maybe we want to start up a server at port 8887. Now we can view that in the browser. However, if we hit that URI, we see that Creating Tasks Controller 2:19need to override the default port, you could do that right here. So maybe we want to start up a server at port 8887. Now we can view that in the browser. However, if we hit that URI, we see that we haven't yet created that controller. So Laravel and PHP are squawking. If I open up a new tab in the command line and I run php artisan, you'll see that Laravel includes some generators that can help us out with this. Notice right here, controller make, that will generate a new resourceful controller. However, in this case, we aren't yet working with resources. You may not be to that point yet, so let's keep it simple. Instead, we will create the file manually within the controllers folder. We'll call it tasks controller. And now within here, class tasks controller extends base controller. So now within our tasks controller, we specified that we wanted to respond with an index method. So for now, why don't we just return show all tasks. Now if I come back Configuring Database and Eloquent 3:06base controller. So now within our tasks controller, we specified that we wanted to respond with an index method. So for now, why don't we just return show all tasks. Now if I come back and I reload the page, sure enough, we hit that controller method and it displayed exactly what we returned. Excellent. So now what would you want to do here? Well, we would basically want to fetch all tasks. Next, we'd want to load a view to display them. So I will add that here too. Now, Laravel offers a very helpful tool called Eloquent, which is what we refer to as an ORM. It gives us an easy way to perform our queries without manually having to write all of this SQL. Now we will be connecting to a MySQL database. So before we can start preparing these queries, we need to go to the config folder and down to database. Here we can see that our default database is set to MySQL. And also I've set some basic configuration options for connecting to mywe need to go to the config folder and down to database. Here we can see that our default database is set to MySQL. And also I've set some basic configuration options for connecting to my database. You will want to make these work for your system. So here our host is localhost. I've specified a database name of Laravel demos, and I've provided a simple username and password that we can use here. If I switch over to SQL Pro, you can see I've already created this database, Laravel demos, but at the moment it's completely empty. All right, so we're good to get started. If I go back to our controller, ideally what I want to do is something like this. Tasks equals task all. Now what this essentially translates to is we want to grab all tasks from the tasks table and store them as a collection within this variable called tasks. However, this task model doesn't exist yet. We need to create it ourselves. So let's do that right now. If I closethe tasks table and store them as a collection within this variable called tasks. However, this task model doesn't exist yet. We need to create it ourselves. So let's do that right now. If I close the config folder, we can add it to our models directory. And notice that by default, Laravel includes a user model to get you started. Let's add it right here, task.php. And once again, we will add our class task. And I need to make sure that it extends Eloquent. Now if we want, we could even leave that plank to start. Because we are extending Eloquent, our task model immediately has access to all of these Eloquent helper methods. And if you'd like to view a full list, just switch over to the documentation. Now we could test it out, but it's still not going to work. I run it, and now we get base table or view not found. So what's happening here is Eloquent is looking for this table called tasks, but we haven't created that table yet. So that's our next step. Now, if Building Tasks Migration 5:33and now we get base table or view not found. So what's happening here is Eloquent is looking for this table called tasks, but we haven't created that table yet. So that's our next step. Now, if you are typically used to going to your MySQL GUI and doing something like this, and then you specify your fields, well, that's not how we're going to do it in Laravel. Instead, we're going to let Laravel do the brunt of the work, and we're also going to get a little bit of version control goodness out of the deal as well. Once again, if I run php artisan, you'll see that Laravel offers these migrate commands. What we want to do is generate a new migration file. So let's set that up. php artisan migrate make. However, if we don't know what arguments and options it accepts, that can be difficult. So let's review the help for it. Now we can see it accepts an argument name, and we can also specify things like, does the table need to be created? If so, Laravel willcan be difficult. So let's review the help for it. Now we can see it accepts an argument name, and we can also specify things like, does the table need to be created? If so, Laravel will provide a little bit of boilerplate code for you. We could specify if it's within a package. We could specify the table name. So let's try this out together. php artisan migrate make. We're going to call this create tasks table. Notice this convention where I basically say exactly what I'm doing, create tasks table. Or what if we needed to add a field to the tasks table? Then we would say add do date to tasks table. Just write it out exactly the way you would speak it. But once again, in this case, create tasks table. And now we can specify that we are creating a new table, and the table name should be called tasks. Let's go ahead and run that, and we can see that it created this new migration file for us. Let's take a look at it. This will be stored within theand the table name should be called tasks. Let's go ahead and run that, and we can see that it created this new migration file for us. Let's take a look at it. This will be stored within the database folder within migrations. Now we can see that we have a class called create tasks table, and now we're using Laravel's schema class to handle the process of declaring what fields we need without us having to write all of that SQL by hand. Now by default, Laravel is going to assume that we want an id that will auto increment that is the primary key. So we can do that with a single line, table increments id. It's also going to assume that you want to create it at and update it at timestamp fields. This is generally a good practice, so try to leave it in unless you have a really good reason why it doesn't belong there. Next, we can add more of our own. So what would a task need? Well, it would need a title, and that should be a type of string. And maybe it alsoreally good reason why it doesn't belong there. Next, we can add more of our own. So what would a task need? Well, it would need a title, and that should be a type of string. And maybe it also needs a body. That should be a text type. Can you think of anything else it needs? Well, we talked about assigning it to a user, so that means we need some way to have a task correspond to a specific user. So eventually we will have a users table, so what we could do is just say table integer user id. So now we're saying we want to have an additional field that will accept an integer that should correspond to the id of the user who created the task. Hopefully that makes sense. Now mostly I think this is fine. The only remaining thing I can think to add is a boolean that will determine whether the task has been completed. And I think that should do the trick. Now the cool thing about migrations is, like I noted earlier, it's sort of version control forthat will determine whether the task has been completed. And I think that should do the trick. Now the cool thing about migrations is, like I noted earlier, it's sort of version control for your database. So when we migrate our database, it's going to create this new table. However, if we need to roll it back, we can specify what form that should take within the down method. And in this case, we just say we want to drop the table tasks because that would be the opposite of creating a table. All right, so now that we have this class, let's migrate the database. php artisan migrate. And there we go. It migrated that file. If I now switch over to SQL Pro and I refresh, we can see it created this migrations table so that it can keep track of where we are in the migration lifecycle. And we also have our new tasks table that has all of these fields. Now what if we made a mistake or we want to roll back? Well, we simply do artisan migrate rollback.in the migration lifecycle. And we also have our new tasks table that has all of these fields. Now what if we made a mistake or we want to roll back? Well, we simply do artisan migrate rollback. And that's going to roll back the last set of migrations he ran. Now if I come back reload, with a single command, we were able to undo what we just did. But in this case, I'm going to run it again, because we do want this. Alright, so now if we try to run this page again, we get an empty array. And that's because yes, it did return all rows from the tasks table, but we don't have any yet. Now we have two ways to do this, we could create a seed file. And that would be a PHP class that declares which rows we want to seed a particular table with. Or we can be lazy here and just hard code it in, go to the store, we need milk, the user ID, we don't have a users table set up yet. But I'll just go ahead and hard code one. And finally, the completed will Rendering Tasks in Views 10:16here and just hard code it in, go to the store, we need milk, the user ID, we don't have a users table set up yet. But I'll just go ahead and hard code one. And finally, the completed will be set to zero. Next, the created at and updated at fields, we'll have to hard code those in. So now if I come back to the browser, refresh, we did return that single row. Now notice how this is returned as JSON. Well, if I go back to my tasks controller, that's a feature that Laravel offers. If you ever return the results of an Eloquent query directly from your route closure or this method, it will automatically be cast to JSON. And that makes it really helpful when you're building things like APIs. However, in our case, we don't want that. We want to load a view and then filter through all of those tasks. So let's do that now. Return view make, and we will load a view within the tasks folder, and that view will be called index. All right, let's go ahead andthen filter through all of those tasks. So let's do that now. Return view make, and we will load a view within the tasks folder, and that view will be called index. All right, let's go ahead and create that now. We'll go down to the views folder, create a new folder called tasks. And within this, we'll create a new file called index.blade.php. For now, I will just paste in some boilerplate. Now to start, why don't we add an h1 that says all tasks, and then we will filter through them. We can do that using Laravel's blade syntax. And that means rather than doing something like this, we can instead say at for each tasks as task, and then end for each. It's just a cleaner way to go about it. Now you might be wondering, how does this view have access to that tasks variable? Well, let's go back to Tasks Controller, and what we see here is that we declared a tasks variable, and then we loaded a view, but we never gave that variable to the view. We can do that in two ways.Well, let's go back to Tasks Controller, and what we see here is that we declared a tasks variable, and then we loaded a view, but we never gave that variable to the view. We can do that in two ways. One, we could say with tasks equals tasks. That would be one way to do it. Or the second way would be as the second argument to view make. Tasks, tasks. That would be another way. Or a third way would be to use a compact function. This is effectively the same thing. It will create an array that has a key tasks, and the value of that key will be equal to the variable tasks. So any of those three ways are perfectly fine. Now we can rest assured that within our view, we have access to a variable called tasks. So within here, why don't we just create a list item, and then we can echo. Once again, using blade, we use this curly brace symbol, which is fairly common for templating, and we'll say task title, and that's it. So now if I come back and reload the page, sure enough, we got ouragain, using blade, we use this curly brace symbol, which is fairly common for templating, and we'll say task title, and that's it. So now if I come back and reload the page, sure enough, we got our first task. If I were to come back and add another one, finish screencast before the wife gets mad. Once again, user ID of one will do this. It's not completed, and the timestamps will be now. If I come back and reload, it will now pull in that row as well. Next, however, it would be nice if I had some way to click on the task so I could view more details. How might we do that? Well, here's what we could do. Let's rewrite this. Within a list item, I'm going to say link to. Now this is a helper function that Laravel provides. We can pass a path like this, and then we can pass the text for the anchor tag, like so. So let's see what this gives us now. If I come back and I reload the page, view the source, notice that it will create the anchor tag for you, and it will set the Adding Task Detail Route 13:42the anchor tag, like so. So let's see what this gives us now. If I come back and I reload the page, view the source, notice that it will create the anchor tag for you, and it will set the href equal to whatever URI that you provide. So in our case, why don't we link to tasks slash, and then the task ID. We can do that with task ID, like so. Now if I come back and reload the page, we have a good link there. So if I click on one of these, we don't have a route registered for that. We're going to have to go back to that routes file. However, we are linking there. So let's go back to that routes file now. Now we'll say route get tasks slash, and now we need a way to specify a wildcard, meaning we want to respond to tasks slash one, but also tasks slash nine. Well, we can do that within braces by specifying essentially a variable name here, and that just means any kind of wildcard, and we're going to name it ID. When that route matches, we want to load tasks controller,do that within braces by specifying essentially a variable name here, and that just means any kind of wildcard, and we're going to name it ID. When that route matches, we want to load tasks controller, and then a show method. Let me open up a split here and return to my tasks controller, and we'll add that method. Show, and now it's going to receive the value of this wildcard here. So if this value is equal to foo, that means the show method is going to receive foo. All right, so within here, why don't we just say return show task with ID of ID. All right, let's try it out. I reload, and sure enough, we get it. So now we have a way to view all tasks. If I click on one, we have a way to view an individual task. However, what if we try to request something that doesn't exist like that? Well, as we know, there will be no row that has that ID in the database. Really, we just want to limit this to integers. So we can do that by saying where ID matchesexist like that? Well, as we know, there will be no row that has that ID in the database. Really, we just want to limit this to integers. So we can do that by saying where ID matches this regular expression, and in this case, we just want to match one or more digits. So now if I reload, notice that we're going to get a not found exception, and that means you don't have a route registered for this. However, if I provide any integer, it will respond. So it's as easy as that in Laravel. Now within here, what do we need to do? Well, fetch single task, and then load a view to display it. Task equals task find by ID, and that basically translates to select star from the tasks table where the ID equals whatever this value is. Once again, let's return task. If we load this again, let's do task one. Sure enough, we get that single task. Very good. Now what if we provide something that doesn't exist? Well, we don't see anything yet. Instead,If we load this again, let's do task one. Sure enough, we get that single task. Very good. Now what if we provide something that doesn't exist? Well, we don't see anything yet. Instead, why don't we call this method find or fail, and that means try to find one, but if you didn't get anything, I want you to fail and throw a model not found exception. That way, we could listen for this if we want, and then display a 404 page or redirect back to the home page, whatever you want to do there. Now that's a little bit above our current level, so let's just stick with this. Now that we've found a task, let's load a view to display it. Return view make tasks.show, and once again, I'm going to send through that task variable to the view. Now we need to create that view, show.blade.php. Now here you can see I'm basically going to have to reproduce all of that HTML, and as we know, that's a bad practice. Instead, why don't we create a master page? Creating Layouts and Show View 17:04that view, show.blade.php. Now here you can see I'm basically going to have to reproduce all of that HTML, and as we know, that's a bad practice. Instead, why don't we create a master page? So within here, I'm going to create a folder called layouts, and within here, we'll create one called master.blade.php. Before I open that, I'm going to copy all of this just to save myself some time. Now we have the basic structure for how all of our views should display. Now within the body tag, I will yield content, and what you might even want to do is something like div class is container, then yield the content, and finally close the div. This means any view that hooks into that content area by creating a section, that's what we call it in Laravel, a section, if the section they create has an ID that matches content, it's going to be inserted right here. Let's hook into that now. Within our show view, we could say extendsLaravel, a section, if the section they create has an ID that matches content, it's going to be inserted right here. Let's hook into that now. Within our show view, we could say extends layouts.master. And by the way, period just gives us a nicer way to say look in the layouts folder and find the master file. Same thing there. Now we'll create a section called content, and within here is where we can say task. Let's try it out. Now if I reload the page and I view the source, we do get our master page, and our section was inserted at the proper location. Great. So now let's just do this. We will create an article element and then echo out the task body like so, and now we'll update the heading to the task title. And there we go. So now, one way to view all tasks, we click on one, and that will take us to the individual task. But it would be nice if there was a way to go back. So why don't we just do this at the bottom. Wrap-Up and Next Steps 18:43one way to view all tasks, we click on one, and that will take us to the individual task. But it would be nice if there was a way to go back. So why don't we just do this at the bottom. We will say link to tasks, and we'll call this go back. All right. And that should do it. One more time. Load the page. We want to go back. Let's view this task. We can see the details, and we can go back. All right. So that's where we're going to stop for this lesson. In the next lesson, we're going to take it a little bit further, and we're going to start learning how can we assign a task to a specific user. So to do that, we're going to have to think about relationships. For example, a task belongs to a user, and a user can have many tasks. We're going to dig into all of that in part two.We're going to dig into all of that in part two.