Get Started With Laravel | FREE COURSE

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so you want to know how to use laravel to build web applications and i can't blame you it is the most popular framework for php which just so happens to be the most popular server side language so i guess that you could say that laravel is extremely popular in the web application space and there's a reason for that laravel is extremely approachable for just about anyone that has a basic understanding of php hi i am jeremy mcpeak and i invite you to spend some time with me so that i can show you just how approachable laravel is we'll start at the very beginning by setting up your environment for developing not just laravel applications but php development in general we'll add the laravel installer to our computer using composer so that we can create laravel projects on the fly we'll then dive right into a laravel project and you'll learn how to create views and route http requests so that you can see those views from there you'll learn about laravel's templating engine called blade and how we can use it to create a consistent flexible and maintainable user interface for our application you'll then learn how to work with data from within your views so that your application can dynamically display data we'll then discuss databases and how you can create modify and even drop tables using migrations we'll also look at eloquent which is how we work with databases from within our application and you'll learn how to work with and handle user input in order to store it within the database so that by the end of this course you'll have the confidence to start writing your own data-driven applications with laravel we have a lot of ground to cover so when you're ready queue up the next video and we will get started of course the first thing that we need to go over is what you need to set up your environment for not just laravel development but just php development in general and we're going to start with what i personally use it's called zamp now one of the things about php is that in order to develop it you have to download and install php you have to have a database engine well not really but if you're going to build anything worthwhile you need the database engine it also helps to have a web server like apache so you have to download and install and configure all of those things manually and if you like doing that then feel free to do so i don't and something like zamp gives you all of those things out of the box they're configured you can even turn on and off the services and that's what i really like about something like this because i don't always want those services running so i can start whichever ones that i need and then i can turn them off whenever i'm done so if that's the way that you want to go feel free to download and install xampp there are of course versions for windows linux and mac os there's also sub versions with different php versions now if you don't want to use zamp but you like the idea of using something like xampp there's also something called mamp and there's nothing wrong with map i used to use mamp and before i went to xampp and the only reason why i did is because at the time they didn't support the version of php that i needed and this page is windows centric however behind the scenes they are detecting that i'm on windows and they are always showing me windows which kind of stinks i would like to see other platforms that are supported but they do support mac os they might support linux i don't really remember if they do or not but that is another option you install it they configure everything you turn on and off the services whenever you want now if you want a more manual approach but you don't want to go to the individual websites and download and install and you're on mac os then homebrew is going to be your option the website is brew.sh and simply search for the packages that you want to download and install onto your machine there is of course php if you wanted to install mysql just do a search for that and you will find the command for installing that as well and then finally laravel makes several tools available in fact they give you a docker image that you can use now if you're not familiar with docker it's not a virtual machine it's more like a virtual operating system so that you can run applications it's a really cool technology and i really like this type of approach because it completely separates your development environment from your main environment which is a practice that i've gotten into personally just because i hate redoing my development environment when i set up a new machine but if you go to the documentation and go to the installation you're going to see your first laravel project and then you're going to see the getting started for whatever operating system that you are on it's going to take you through the steps of using docker now unfortunately we're not going to take this route in this course it's a really awesome way of setting up an environment however my docker installation is hosed after i upgraded it but if you wanted to take this route then feel free to do so the instructions are very clear just follow them and you will be good to go so in our case what we want to do is install laravel with composer now if you don't have composer this is a package manager for php i believe the website is get composer but if you just do a search for composer there it is getcomposer.org download and install it on your machine and then from there you'll want to open up a command line so that's you can install the laravel installer now there is the option to not install the laravel installer and just run it off of the web however i personally like to install the installer so that well it just speeds things up so from the command line after you install composer you will want to type composer global require laravel slash installer and then this is going to install the laravel installer on your machine so that whenever it's done then we can create a new application by using the laravel command we will follow that up with new and then we will name our project i'll just call this first dash app this is going to install our application it's going to set everything up so that whenever this is done we can cd into that directory fire up our code editor we can even fire up the application itself and we will see it up and running when the installer is done then we will of course went to cd into first app we can go ahead and fire up our code editor but most important we can run our application using artisan which is a command line interface for laravel and we'll say php artisan serve that will run our application and it tells us where to go so let's hop on over to the browser we want to go to localhost port 8000 and we will see our application there's not going to be a whole lot there but we can at least see that it is up and running and in the next lesson we will see how this page is processed and sent to the browser laravel is a framework for building dynamic websites i know that that sounds painfully obvious but it's a distinction that i want to make because we almost have to get into a completely different mindset when it comes to building dynamic websites because what we see in the browser is not the result of just reading a file on the file system that's what a static website does so if this were a static website and if we tried to go to about.html well the web server on that static website would try to find that file called about.html if it found it it would read that file and then return the contents back to the browser there's no logic there's no processing there's nothing it's just simply reading the file and then returning it now of course if it couldn't find that file then it would return a 404 because that file didn't exist but that's a static website in a laravel application what we see is the result of executing a function or a method on the class so if we try to go to slash about within our application it's not that our application couldn't find a file called about it's that we haven't written the code that's going to execute whenever we make a request for that url but that's very easy to do all we have to do is create a route for that url and we do that by opening up our routes file if you go to the routes folder open up web.php and we're going to see a very simple file there's just really four lines of useful code there's also some comments if you want to read that that's fine but let's first of all look at what we have on line 16. so there's already one route defined it's for a get request for the url of just a slash that is essentially our home page you could also call it the root of our application so whenever our application receives a request for our home page it's going to execute the function that is specified here and all it does is call another function called view so what we see in the browser for our home page is nothing more than the result of calling that view function and then passing in the string of welcome we'll talk about that later but let's do this let's change the output here so let's just say hello laravel and whenever we view this in the browser let's just refresh that's all we see there's nothing else and we can even view the page source and once again that's all we see it's not adding anything extra and it's only returning the content that we have specified so we have complete and total control over what we return for whatever url and this is very powerful because we can return anything it doesn't have to be just text or html or css or javascript it can be binary data like a pdf or an image or anything we just have to write the code that's going to do it and that sounds like a lot of work and in some cases it is but for the most part it's it's not so let's change this though let's add some html let's make it not just plain text but big and bold plain text so once again we refresh we can obviously see that the styling there changed if we look at the source of the page we can see that that was also updated as well so once again whatever we are returning from our routing functions is going to be what is sent back to the browser well let's do this we talked about an about page so we need to write the code that's going to handle that request so we want to start with the route facade then we need to decide what kind of request we want to handle here well we only really want to handle a get request in this case and we want the url to be about so we will then specify our function that is going to return the content for this url we could just let's use an h4 in this case and we can say about page let's close the h4 and there we go so now our application has two routes we have one for the home page one for the about page so if we go back to the browser the home page is now showing us what we did before because i changed that back to using the view function but if we go to about then we see the about page okay so that's great let's talk a little bit about this view function so laravel is what we call an mvc framework m stands for model that's essentially the data of our application v stands for view which is the user interface of our application and then c is controller and the controller is well it's kind of the glue between the data and the user interface so what we could see here is that for our home page we are returning the user interface called welcome and we can see that inside of the resources folder and then there's the views folder then there's a file called welcome.blade.php so let's open that up and we are going to see some html in fact there's more than html if you look a little closer you're going to see some stuff that kind of looks like php laravel has a templating engine called blade you could also call it a view engine and that's the term that i will use a view engine called blade so the name welcome is the name of the view that's what we are looking at blade is the name of the view engine and then of course it's a php file so there's a lot of stuff going on whenever this view function is being called that's executing the view engine to load the welcome view and then to process that view and make the decisions that it needs to make based upon some of these logic decisions and so on and so forth the end result is of course what we would then see inside of the browser so there's two very important things i want you to take away from this lesson first of all our application is only going to handle the urls that we specify and we set up those urls by creating a route so that our application can route a request to the code for that url the second thing that i want you to remember is that these routes can do anything they can return any kind of content it can be text it can be binary it can be anything because we are the ones that have to write the code for those routes and in the next lesson we're going to take things a little bit further you're going to learn how we can extract data from the url in this lesson we are going to be talking about user input because our applications are interactive they accept user input now one very important thing to be aware of is that a web application is actually at least two other applications there's the application that runs within the browser that's the client application and we aren't really that concerned with the client application we are concerned with the server application that is our laravel application now of course yes the laravel application is going to supply the content that is going to be in the client application but we won't worry about that right now think in terms of a server side application our server is just sitting there doing nothing until it receives a request and that request always contains information from the user that information could be the result of the user filling out a form and submitting it or it could be something as simple as the user typing in the url in the browser and then hitting enter so that they go to a particular page it doesn't matter what kind of request or what generated the request if the user initiated that request that is our user input so in this and the next lesson we are going to be talking about urls and specifically how we can pull information from the url because that's one of the primary ways that the user will provide input for our application so in this lesson we're going to be talking about query strings so let's assume that we are going to build a store that sells musical instruments so we will have a url that is slash store but then we need to know what types of products to show so you know the slash store could be the generalized url to where we show kind of a little bit of everything but then if we wanted to filter the results like on category so if we wanted to show only guitars then we could have a category query parameter and its value could be guitars that is a very common use of a query string so let's write the code that's going to be looking for that type of url let's first of all add a new route so that we have a new endpoint here the url is going to be slash store and then we of course need the function that's going to execute for this particular route so for right now let's just return a string that says you are viewing the store the reason being we want to make sure that we have some code that works here and of course this is something very simplistic but it's always a good thing to see code that works and there we go we are viewing the store that's great so let's say that we want to now pull in the information from that category query parameter well we have a built-in function called request and then we simply pass it the string of the query parameter that we want to get the value for so in this case it's going to be category just nothing complex about this so let's store this in a variable we'll just call that category and then we could use this in the output so that we are viewing the store for and then we can concatenate that category so we would have category there we can go back to the browser let's add the query string so that we will have category and then we will start off with guitars so now we see you are viewing the store for guitars and no matter what we change the category to be the content that is displayed in the browser is of course going to change accordingly now that's all well and good but the first rule of handling user input is to never trust users that might sound a little harsh to hear but yes the vast majority of people are nice people they don't care about your application as long as it works but there's just the small few that will want to do something malicious and it doesn't matter how big or small your application is if it's on the internet you are at risk and you are a potential target so never trust user input because somebody could do something like this instead of submitting just a typical string for category we are going to alert let's just say hi and chrome or this isn't chrome this is edge but it's built on chrome is going to wow i did not expect that that's good to know so you can see what just happened and the reason is there is very simple if we view the source we are going to see that the script that we typed in the query string was output directly into the html let's see if i have chrome installed i do i don't use chrome very much anymore this just personal preference but chrome will actually block that so if we open this up in chrome we will okay chrome used to protect you from this but you can see the problem here if we can inject something as simple as an alert box then an attacker can inject something far more sophisticated that would then cause a lot more damage so we want to protect our applications as much as possible and it is our responsibility to do that they are our applications we are responsible for them so to fix this one thing we can do is just take the value from the query string and then pass that to strip tags and if we view this in the browser then we are not going to see that alert box display thankfully and instead we just see the text that was inside of the script tags now as we start talking about views and the blade view engine there are other tools that we can use but for right now this is going to work just fine so just be aware that the user can supply malicious code you want to protect your application from that code as much as possible so we typically call that sanitizing inputs always sanitize your inputs so instead of stripping tags wherever i use category i'm going to strip tags whenever i grab the value from category that's a much safer approach there now that's all well and good but what if there's not a category in the query stream and that is a valid url because if the user just goes to slash store then we would want to show just all of the instruments and right now we just say you are viewing the store for and there's nothing else there so this is where we can start to introduce some logic here so we're going to take out this call to strip tags we still need to do that but we'll do that a little later so for right now we are going to attempt to get the value of the category query parameter now i say attempt because it's either there or it's not and if it is then great we have something in the category variable so that we could check if it is set so if it is set then we of course want to display our message that they are viewing the store for that category but this is where we want to use strip tags so once again we will call strip tags right there but if we don't have a category then we just want to show all of the instruments so we will just have that content you are viewing all instruments so if we save this our code is still going to work if we refresh the page we are viewing all instruments but if we specify category then we will see the store for that category and so that is how we work with data in the query string we retrieve the information from the query stream by using the request function we simply pass in the query parameter that we want to get the value for but remember always remember to never trust user input so before we output that input we want to sanitize it and in our case we strip out all of the html tags now there's more things that we need to do in order to protect ourselves and our application but we will talk about that when we start getting into databases for right now this is going to be sufficient and if we don't have a category then we display the content for all of our instruments well in the next lesson we are still going to be talking about urls but we are going to be talking about url wildcards because while this works and this has been around for tens of years 20 30 years okay maybe not 30 years but it's been around for a while we tend to not do that anymore instead we might have a url that looks like this to where we have store slash guitars or drums or whatever category that we want to display here and we will look at how we can handle those kinds of urls in the next lesson in the previous lesson you learned how we can pull data from the url query string it was really straightforward we just use the request function pass in the query parameter name and then that will give us the value for that parameter if that parameter is in the query string otherwise we don't get anything so if you need to rely upon that value you need to make sure that you have a value to work with otherwise your code is going to break so in our case if we had a category we simply displayed content for that particular category otherwise we showed the generalized content for just all of the instruments so that's all well and good however that means that we have a url that looks like this it has a query string and the problem with query strings is that it makes the url less friendly i mean for us our brains are automatically parsing this out as we look at it so it makes it some sense to us but for non-technical people they're not really going to remember this and it gets even worse if we have characters that have to be url encoded and then you can also make the argument that we really shouldn't even be using a url like this for displaying like the categories or a particular item within a category and instead we would do something like this to where we would have of course store but then we would have the category and then the item this is much much cleaner it's also easier to remember and it also makes a whole lot of sense because from left to right we are going from something that is very generic to something that is specific and the more we go to the right the more specific things get whereas with the query string the order of the parameters doesn't matter at all what matters is that they're there or they're not so you can end up with urls that make absolutely no sense whatsoever but again to us they do but for normal people they don't so having a clean and a hackable url what do i mean by that well we can keep taking segments off or adding segments in order to filter down the content even more i mean we could take that to the extreme to where we would have the store followed by the category followed by the manufacturer followed by the individual item or if there were different lines of products from this manufacturer you could have a line one and then you could have the item i mean you can make things kind of absurd and of course the more segments that you add to a url the more difficult it is going to be to remember it you want something that's nice easy for people to remember so in our case we're going to stick with just this three segments in the url store category and item and we can make this work very easily by using route parameters so i'm going to take our store route i'm going to copy it and we'll comment out the current version so that we can replace it with this new version and our url is going to start off the same because we want this to be for our store so the store is always going to be part of the url but then we want to specify the individual segments that are going to be dynamic and we do that using a set of curly braces and then inside of the curly braces we have the route parameter so we have store followed by the route parameter for category followed by the route parameter for the item and these map directly to parameters to the function that is handling this route and there is a direct link between the names so the route parameter category maps to the function parameter category so this means that the names of your route parameters have to be valid php identifiers but the beauty of this approach is that now the information is in the url and it's automatically being passed to the function so we don't even have to use the request function here so the first thing we can do is check to see if we have a category and if we do then we can start branching our code here because if we have a category then we possibly have an item if we don't have a category we don't have an item so inside of our check to see if we have a category we will do essentially the same thing for the item and if we have an item then we will show the content for that particular item otherwise we will just show the content for the category so as far as our item content is concerned i will do this you are viewing the store for and then we will include the category another nice thing about this approach is that you don't really have to strip tags or sanitize this because if there's any characters that are not valid url characters then this isn't going to work at all so in this particular case we don't have to strip tags for category because if there were tags in the segment of the url it would not be a valid url and so we will finish this up with the individual item so there we go we have our content for the individual item we have the content of for the category then finally we have the content for just the store in general so if we go to the browser let's refresh the page here we're going to see that it doesn't work 404 and this is why because by default the route parameters are required we have defined a url with three segments it starts with store but then we have two segments defined after that so what we want to do is make these route parameters optional and we do that by just following up the identifier with a question mark so we will have category question mark and then item question mark then we can give default values to our function parameters and then our code is going to work so if we go back to the browser let's refresh now we see the all instruments content if we look at uh just pianos i don't know if it's es or just s doesn't matter if we look at pianos then we can see that we are viewing the store for pianos and then if we wanted to look at a steinway then we can see that we are looking at the store for pianos for steinway and so that is how we can build clean and memorable urls we simply define parameters inside of our route and match them up with a function parameter if we want the parameters to be optional then we have to follow that parameter with a question mark we also need to provide a default value for the function parameter and in most cases you will want to use url parameters there are some cases where it makes sense to use a query string but i would argue that those are few and far between so far we have been using closures to define our routes and for small applications that's perfectly fine however as our applications grow as we add more routes and especially as our routes become more complex well this can be very cluttered so what we want to do is start to organize our code into logical chunks like for example there are three routes two of them are somewhat related we have the welcome page and then we have the about page and even though those are completely different routes they serve somewhat the same purpose in that they provide content for well kind of the home part of the application it's not necessarily a home page but you know there's the welcome page there's an about page if we had a contact page i would say that this is part of the home content so let's add a contact page that would be nice to have so if there was anything that was just generic to the website itself then i would consider that part of the home content and so we could put those routes inside of their own file but then we would have a separate file for the store route and any other routes that we would need to write for the store we would put inside of that same file if we had some other content that wasn't related to the home stuff or the store but let's say that we had some information about different kinds of collections like there are some music stores that will have a collection of stuff that they don't sell but you know they still collect it so if the store collects guitars then we could have a guitars route and then from there there could be individual pages for individual guitars that they would want to provide content for you know so that would be in a completely separate file because that had nothing to do with the home stuff or the store it would be just the guitars so we want to start to create these new files that contain the functionality for these routes because in actuality we still need to define our routes here inside of this web.php file but as far as the code that's handling those routes we want to define that elsewhere so we are going to create what are called controllers now if you'll remember from a few lessons ago i said that laravel is an mvc framework that stands for model view controllers controllers are classes that have methods we call them action methods and those action methods handle requests and that's basically it that sounds very simplistic and in a lot of cases it is that simplistic however in other cases it's not so in this lesson we are going to create a home controller for all of this home oriented content so let's go to the app folder let's open up http and then there's going to be a controllers folder and you can see that there's already a file in here called controller.php this is the base controller class that you don't have to use in fact you can write a controller that would be just a normal class doesn't inherit from any other class and you would be fine there but this controller class has a lot of utilities that you would probably want to use so it makes sense to create a controller class that would inherit from this so we could create a new file here we could call it home controller the name really doesn't matter but remember that we want this to be logical we don't want to just call it something random this is stuff oriented to the home content so we started with home and we followed it up with controller so we know that this is the controller for all of the home stuff it just makes sense so we could take this route or we could use artisan artisan is the cli for laravel and we're going to use artisan because it's a fantastic tool that gives us a lot of functionality in fact if you just type php artisan you're going to see everything that it can do for us there's quite a lot even just the make portion which is what we want to do because we want to make a controller but you can see that there's a lot of things that you can make with artisan and the great thing is every one of these commands have their own options and artisan is just going to stub out exactly what we want it to so let's look at php artisan make controller dash h that's going to show the help for the make controller command and you can see that there are several other things one of note is this resource we're not going to look at a resource controller class in this lesson but we will definitely use this and you will definitely use it in your applications and the great thing about this is if you do use the dash r flag it's going to generate a class that has all of the methods for creating a resource controller so artisan is a fantastic tool we need to use it so php artisan make controller and then we just follow that up with the name of the controller that we want to create home controller and then there we go we have our class if we go back to our code we can see that there is now a homecontroller.php file inside of our controllers folder it gives us the class it inherits from controller so now we just need to write our action methods so we will start with the welcome page which we could call welcome but since this is kind of the home page or the index page i guess we should use index page i'm going to call this index that's just convention you don't have to follow convention but convention is there well because it's convention and all we are going to do is return the view we are basically going to take the contents of this closure we could just cut that out we could paste this here and then just give it the name of index so we will say public function index and then voila we'll do the same thing for the about and contact so let's cut and then we will paste and let's give this a name of about and then finally we will do the same thing for contact but since we already have that functionality we'll just copy about so there we go we have our controller all we need to do then is link the action methods that we've defined here to the routes and we do that very easily the first thing we need to do is import that home controller so that is inside of app http controllers and then we will bring in home controller and this is what we will do we are still going to say route and then get we still specify our url but the second argument that we pass is going to be an array where the first element is the class that we are going to use home controller in this case and then the second element is going to be the name of the method that we want to use so index in that case so we'll just copy that paste it a couple of times and then make the necessary changes so for about it's going to use the about method and then contact will use the contact method so this is much cleaner and our code is still going to work just like it did before so if we go to the browser let's refresh this page and well we have something wrong app http controller oh controllers it's amazing what one keystroke will do so there we go we have that if we go to about we're going to see our about page if we go to contact which we just added we will see our contact page views are essentially the user interface in a laravel application they are what generates the markup that is then sent to the browser but a view is so much more than just markup it's in fact a template that has to be processed in order to generate that markup and we have very briefly looked at views they are inside of the resources folder and then views and then the only view we have is the welcome view welcome.blade.php that is of course what we see when we go to the index of our home controller that is the welcome and while the majority of this file is markup there are some templating directives that have to be processed like for example here is an if block it's basically determining if the route has login if it does then this content is going to be shown but there's more than just this content because there are templating expressions really that have to be evaluated and processed and then ultimately rendered into markup so what we are going to do starting in this lesson is spend some time with views because well they are very important to our applications and we're going to start by creating an about view for our about action method so let's open up our home controller that is app http controllers and then home controller and basically what we want is a single view for every action that is going to return a view now it is technically true that we could reuse this welcome view we could add in the if checks to determine whether or not if it's a welcome or about or contact and we can put all of the content inside of welcome if we wanted however we don't want to do that because that's going to really clutter up our welcome view so we essentially want a single view for a single action method so this means that we need an about view and a contact view now we can create those from scratch or we can just copy the welcome view and use that as a basis so let's do that and let's rename the copy to about.blade.php now the name of the file is arbitrary there is no magic linkage between the name of the file and then the action method that we are going to use that view for because whenever we call the view function we have to specify the name of the view that we want to use so in this case about so you can call your views whatever you want but it makes sense to name the views according to the action method that they're going to be used for so we've created an about view we will do the same thing for the contact view but let's first of all change some of this content for about because we can go to about now and we are going to see the exact same thing that we would for the index although it would help if we saved the controller so let's save that file and then refresh and then there we go so we want something that's a little bit different and we can do that by just starting to delete a lot of stuff here all right so this div element right here has this svg this is the laravel logo and branding there so let's get rid of that and let's just have an h1 to where we say about us and then we want some content that is just going to have like a p element and that'll be it so let's get rid of most of this stuff and let's see let's go all the way down here i think that's it yep everything else lines up and then this is where we will have our p element this is the about page and let's also change up some of this styling here we'll change the background color to be whatever is the pages let's get rid of the shadow and the rounded border okay so if now we look at our about page this is what we have it's very bland but it is at least very different so that's great and we can use this as a basis for our contact view so let's just copy that file let's rename that to contact dot blade dot php and then let's make the appropriate changes so that this says contact us and this is the contact page we of course need to change our home controller so that we will now call view inside of the contact action method and we want to use the contact view there so if we go to slash contact then there we go we will see the contact us now i would like some way to navigate between these different views so let's add some navigation and we won't do anything too fancy we'll just add a nav bar at the top so we'll start with a div let's reuse this relative class and then we're also going to add in a padding now this does not exist in the classes that are defined in the template so we will need to define this but we're going to say p dash 4 and then inside of here we'll have our nav and then we will have our links and we'll have one for each page so we'll start off with the welcome we'll just call that home because that's typically what we would see and then we will have the about which will be to slash about the text we could say about us but let's just keep it nice and clean and we'll just have about and contact there so let's view this in the oh we do need to define this p4 class don't we we can do that in this second style here so i will say p4 we'll say the padding is going to be one rem and if we go to the browser let's refresh and that's okay let's put some padding in between the links here and we could add classes but let's do this we'll just say nav a and then we will say that the padding is going to be uh let's say 0.5 rem and that should give us some spacing there that looks good all right so now we just have to replicate that inside of the other pages so let's start with the markup itself we'll go to the about page and we will paste that in at the top we will also need to do that on the welcome and i really have no idea what this is going to look like this might look horrible but we will soon find out and then we need the css there so let's go back to our contact view let's copy the css and then we will paste it into the about view and then the welcome view let's go to the about page that looks great let's go to home and okay that looks great as well so now we have views for each one of our content pages and we also can navigate between them but well that was kind of cumbersome wasn't it we had to copy the markup that we wanted paste it into the appropriate files and if we added more views we would have to do the same thing for each individual view as long as we wanted to keep this same nav bar at the top and that's very cumbersome but thankfully we can create what are called layouts that allows us to define essentially the layout of our application and we will look at that in the next lesson in the previous lesson we created two new views one for about the other for contact and we also created this nifty little menu so that we can navigate in between our different endpoints and we added that to each one of these views including the existing welcome view and that's all well and good but the problem is how we went about implementing that we first of all copied all of the markup for the menu and we went inside of each individual view file and pasted it into the correct place we also needed to paste in some css rules so that it would be displayed how we wanted it and you know for a small amount of views that's okay i guess you could say but as our application grows that's just not feasible that is a maintenance nightmare because any change that we would make we would have to go into each individual view and make those changes so the way that we get around that is by using what's called a layout it is a specialized view that essentially contains all of the layout of our application and what is the layout well it's basically all of this boilerplate stuff that all of our views use so the layout in our case would start with the dot type and it would consist of basically everything inside of our view except for the actual content which we could say would be this this div with the class of max w 6xl and so on and so forth this would be the content so let's start by creating a new file and since this is the layout view we're going to call it simply layout and dotblade.php and we are going to take the entire contents of about and then paste it inside of layout and the only thing that we want to take out is what we would consider the actual content so we're going to delete that from inside of our layout and for right now we're going to have the content placeholder this is where we will put our content we'll get to that let's go to our about view and we want to get rid of practically everything except the content so let's go ahead and let's do that and then we need to tell this about view that we want to use the layout that we just created and we do that with a directive a directive in blade templates basically starts with an at sign and in this case we're going to use a directive called extend now this is a lot like the extends that's used for classes you have a class that extends a base class well here we have a view that is going to extend a layout and then we simply just pass in the name of the view that we want to use as the layout and there we go but that's not enough we also need to create a section that essentially denotes that we have some content here so we can just call the section content because well that's what it is and then we would denote the end of that section so that's in between the section and in section that is the content section so now we just need to display this inside of the layout and we do that with a special directive called yield we pass in the name of the section that we want to yield and there we go so content in this case so if we go to the about view let's just hit refresh it's going to look the exact same but to prove that we are using the layouts we can do anything uh we can just put layout in front of the yield directive and we will see layout somewhere right over there alright so we have this layout that we are now using and we just need to update the other views to use the layout let's start by going to the about view let's copy the extends and the opening section and then we will replace everything before the content with that then we will close out the section with the end section directive and i'm going to change the formatting here just so that it looks nice and clean and we can do the same thing for the welcome view so let's find that though in this particular case uh the content starts here really so we want to get rid of everything before that and i guess we should have done it like this so that we could collapse everything so that we can see what is and isn't going to be content so this would be the end section here then we would have layout and section directive there so there we go we have our views and of course we can go to the browser and view this just to make sure that everything looks okay and it should so let's go to about that's great we can go to contact and we can go to home everything looks the same as it did before now something else that you might want to do is add another section because this gives us the flexibility to do that so let's say that we might want to have a certain javascript on certain pages so we could have a section called scripts so that if we had that section defined let's say inside of contact because that would make sense this would be a contact form really so we would have some javascript for client-side validation and stuff like that so we would have a section called scripts and then we would have our script here and let's just do this we will say alert contact us just so that we can see that happening that'll probably get annoying here in a little bit but that's okay and there we will have our in section directive so if we go to contact now we can see that we have that contact us but if we go to about there's no error or anything else it just recognizes that there wasn't a section called scripts inside of the about view so there was no reason to actually output anything as far as the scripts are concerned and that's all well and good but something else that we could use this for is like the title because each one of these pages would have a different title so here we could inside of the title element we could yield well let's just call it title so that's inside of our other views we will simply just specify this section and this is going to be a little bit different we can still do that the same way that we have done with the section directive and then the end section directive but since this is something much more simple what we can do is this we still need section we still need to specify the name of that section but we can pass in a second argument which would be the value that would be displayed for this section so that this is about this could be about us and then let's just copy and paste this so that we can add the title to those others so there is still some repetition at least as far as copying and pasting is is concerned but it's mostly for showing different content it's not so much showing the same thing across all of the views so let's go to welcome we will add that section and this will just say welcome so now we can go back to the browser and we can definitely see in the tabs now we have about us so if we go home we'll see welcome if we go to contact we'll see contact us along with our script so layout views are very important they allow us to define essentially the layout of our application the key thing to remember is to use the extends directive inside of your views so that they will use the layout and then to yield the sections that you want the layout to well yield valid and correct urls are very important in fact they are probably the most important thing in a web application because without correct urls well nothing is going to work and it's not just navigating from page to page it's also linking to other resources like css javascript images you know things like that so in this lesson we are going to look at two things first of all where you can put your static resources the second thing is how to link to them and it might sound obvious but there are some issues there so let's start by looking at where we can put our static resources and that is inside of the public folder now there are already some files in here one of those is this index.php this is well all of the files within our application are important but this one is the entry point of our application so without this nothing works but if you scroll down you can see where the bootstrap file is being pulled in now that is not the css framework that is bootstrapping this application and it's creating the application uh handling the request and getting the response so this is a very important file we want to leave it alone so let's just close out of it before we really screw something up and everything inside of this public folder is considered at the root of our application so what exactly does that mean well this index.php for example the url for that would then be um let's see we are at localhost port slash and then index.php the robots would be robots.txt and so on and so forth so this is where we can put our static resources like our css and stuff like that and that is exactly what we are going to do we are going to create a new folder called css and then inside of there we will create a new file called site.css and we are going to take the css inside of the style element so that is this body rule as well as the p4 class we created and then the rule for our navigation and we are going to put that inside of site.css which then means that we need to link to that so we will use a link element and the url uh well that should be css site.css that should work just fine so let's go to the about page let's refresh and everything looks like it did before so that's great but let's look at this we're going to change the route for about and all we are going to do is just say slash about slash about so if we go back to the browser let's refresh this page we're going to get a 404 because we no longer have a page at just slash about we have to go to slash about slash about and this is going to look mostly the same but notice the menu the styling is off and the reason is very simple the browser is looking for our site.css in the wrong place so let's copy that link address and we'll take a look at that so it is looking for the css folder which we know is at the root because we put that inside of the public folder it's looking for that css folder inside of about and that is definitely wrong now there are some ways that we can get around this but there is a foolproof way that's just going to make it so that we don't have to even think about this all we have to do is use a utility that the blade templating engine gives us it's a function called url so let's go back to our layout page and instead of just directly putting the url inside of the href we are going to use this url function to where we pass in the relative url and the magic is just going to happen so if we go back to the browser refresh the about slash about we can see that now it is pulling in the appropriate css file if we go to any one of these other views then everything is going to look the same because the url is going to be correct so when it comes to not just linking to static resources but any resource within our application it makes sense to use the url function because all we have to do is supply the relative url and it's going to generate the appropriate url and we don't ever have to worry about having an incorrect url once again now in the next lesson we are going to take this a step further and we are going to look at how we can generate urls based upon routes so that once again we don't have to worry about thinking of what is the correct url for the correct route blade will just handle that for us in the previous lesson we looked at the url function and how it can fool proof the urls for our application's resources i mean we don't have to think about it we just pass in the relative url to that url function and we're good to go and it would be nice if we could do the same thing for our routes and we could i mean technically we could use the url function so for our home we could say url and then use the slash there and then that would link to our home page or the welcome page but i want something a little more robust because urls change they don't change very often but they do change and i would like the application to adapt to those changes so that if we ever just change the url of our route like we did for the about then that would just automatically be reflected in other parts of the application and we have that capability instead of using url there's another function called route but we don't pass in a url we pass in the name of that route so let's first of all look at how we can name our routes and it's very simple all we have to do is chain a call to the name method whenever we define a route so here we are setting up the route for the get request for the index on our home controller so the name in this case could be index but as you'll see as you add more controllers you're going to have a lot of indexes so it makes a lot of sense to use the name of the controller and then the name of the action on that controller and i use a dot in between those two values so that we will have home index and then we can essentially do the same thing for about and contact then we just need to make the necessary changes and there we go we have named our routes they are unique that's very important our routes need to have unique names and so now we can use those names to generate the urls so for the home page that was home index then let's just copy and paste and then we will make the necessary changes for the about route and then the contact route so let's go back to the browser let's refresh now we know that the about is different because we changed that in the previous lesson it is slash about slash about so let's inspect this and we can look at the url that was generated and there it is slash about slash about so if we click on this it's going to automatically take us to the about page that's great of course if we click on home we see the index view so let's change our url back to just slash about because that's what we want anyway then all we have to do is just refresh the page if we look at the about link we can see that the url is now updated we don't have to worry about that at all so as you are linking to other routes it makes a lot of sense to name your routes so that you can use the route function to generate the url for those routes it takes just a few seconds but it saves you a whole lot of headache later on we need to start moving towards working with data so in this lesson we are going to create a resource controller and we will also talk about what a resource controller is but we will also wire everything up as far as the routes as well as the first few views that we are going to use to display some things so let's start by creating a resource controller we will use artisan to do that because well it just makes it so much easier to do it especially with a resource controller and you'll see why and i could explain to you what a resource controller is but it's just a whole lot easier just to show you and that's what we're going to do so the command is php artisan make controller and then the name of the controller that you want to create this is going to be a resource controller for guitars and then the resource flag the option is to have just dash r but i like verbosity when it comes to commands like this because as i'm looking at the screen i want to see that this is a resource what the heck is dash r so here we go we've just created our controller and it's going to end up in the same place as our home controller so that is app http controllers and then there's guitars controller and there's going to be a lot here so this is why artisan makes this so much easier because if you're going to create a resource controller then you would have to implement all of these methods okay so what is a resource controller well a resource is really nothing more than a single type of data that your application is going to work with and the controller contains all of the action methods for working with that particular type of resource so what do we do with the resource well it's primarily four things we create read update and delete we refer to that as crud c-r-u-d and a resource controller provides everything necessary for a resource so in this particular case a resource is a guitar now it would be great if it was an actual guitar but no it's just the uh information about the guitar things that we would store in the database such as the name the manufacturer the year that it was manufactured and things like that so i'm going to mark some of these with the types of http requests that are used so index would be for showing all of the particular resource so since this is a guitars controller the index action method would be for displaying all of the guitars in the database so that is a get request create is a get request because when it comes to creating a resource you essentially need two things you need a get request for showing the ui for creating that resource and then you need the method for actually creating that resource in the database so the create method is for showing the ui for creating a resource the store method is for actually storing or creating that resource in the database then there's the show method which is for showing an individual resource so this would use the provided id to fetch the appropriate record out of the database and then this would show that information the edit is a get request for showing the ui for editing a particular resource with the given id and then that is followed up with update which is for actually updating the item that you want to edit now this is a little bit different because the update action method will execute differently based upon what was actually requesting it if it was a request from the web browser from the actual web form it would be a post request because browsers don't support any other kinds of requests except and post when it's coming from a form now if it's coming from javascript then it can be a put or a patch it depends upon the type of update that you are going to do but since we will be dealing primarily with just a form it is going to be post so we'll just leave it as post and then destroy which is for removing or deleting a resource so this would be deleting a record from the database and that is the delete http method let's start with the index and we are going to return a view we'll call that view index because me personally when it comes to views i like to associate the views with the action methods just because it makes it easier for my brain to link those two things together so let's go ahead and let's create that view we'll go to the resources views folder but before we create this file let's think about the future because any application is probably going to have multiple controllers some of those controllers will more than likely be resource controllers so that means we will have multiple index action methods which means that we will have multiple index views so it makes sense to start organizing our views according to the controllers that are going to use them so inside of the views folder i'm going to create a new folder simply called guitars the idea being that this is the folder that contains the views for the guitars controller that's the typical convention you can use whatever convention you want and then inside of this guitars folder we will create a new file called index.blade.php let's go ahead and extend the layout let's also go ahead and define the section for the content and we'll just say that this is content in the next lesson we will actually provide some content here and we of course need to close out that section so that's our view we'll close that for now but since our view is inside of a different folder we need to change the name of the view that we want to use it can't just be index anymore because that would be a file directly inside of the views folder we need to specify that it is in the guitars folder and we do that just with guitars followed by a dot and then the name of that view so guitars.index when it comes time to implement the create ui or the create view it would be guitars.create then we would have guitars.show and so on and so forth so with that setup all we have to do is wire up the routes so let's go to our routes and we could define each individual route for each individual action method but no i mean you can if you want to but times valuable we are going to use a method called resource and it is going to do all of the work for us it's not only going to create the routes but it's also going to give them unique names so that we don't really have to worry about anything all we have to do is pass in kind of the url prefix that we would want to use so by using guitars here this means that all of the routes are going to be based upon slash guitars so our index is just going to be slash guitars but the creates method would be create the edit method would be edit in order to display an individual guitar it would just be the id from the database so we don't have to worry about any of that at all calling this resource method passing in guitars is going to automatically do that for us so that then all we need to do is specify what controller is going to be used and that is simply guitars controller class and we do need to import that don't we so let's just copy what we did for home controller and then make the necessary changes there and there we go so let's add a link now remember i said that this is automatically going to name the routes for us we don't have to worry about that and it's very simple it's going to start with guitars which is the name that we passed as the first argument followed by the action method that's it guitars.index will be the name for the index route guitars.create guitars.store guitars.show so it kind of falls in line with the naming scheme for the views as well so let's open up about let's add a link to guitars let's put this after home and all we need to do is say guitars.index we will have our guitars there so as long as i saved all of the files uh this should work let's refresh here inside of our menu we should see guitars we do if we click on guitars everything should still be there and then this is content so we are seeing the content from the guitars index view so in the next lesson we are going to actually display information we're going to pass data to the view so that we can work with that data to display the information in this lesson we are going to start working with data now for right now the data is going to be static and that it will be hard coded into the application but eventually once we get into working with databases we will remove this static data so that we can work with actual data so i have pasted in a method called get data it simply returns an array of arrays and each one of those arrays have an id to represent the record id and then the name of a guitar and then the brand of that guitar and we just want to display this information so the first thing we need to do is pass this data to the view and the way that we do that is by passing a second argument in the view function it's an array where the keys are essentially the variables that we are going to use inside of the view so it makes sense to just call this guitars and then the data for this will be from calling the get data method let's also do this let's assume that for whatever reason we are handling user input so the user fill out a form and we want to do something with that data in the view now we aren't going to sanitize anything here but i want to stress sanitize your inputs this is strictly for demonstration purposes so please remember to sanitize your inputs but in this case we aren't we are going to assume that the user that submitted the form is trying to inject some highly malicious javascript so that they can well alert a message that says hello so this allows us to pass as much information to the view as we need and we have complete control over how we refer to that information all right so let's go to the view and let's just start implementing this so instead of our content let's start with the div element that was being used in the about and contact views so this one right there and we will encapsulate everything inside of that div there so we have our guitars and it's an array so we want to display the list that means we need to loop over that array so we have a for each directive which is pretty much exactly like the for each loop in php except that it begins with at for each and it ends with end for each there are no curly braces or anything like that but other than that it's just a normal for each loop so that inside of the parentheses we have guitars as guitar and then we just need to output the html which let's have a div that's going to have an h3 element where we are going to output the guitar's name and then we will have an unordered list where the list item will have made by and then we will include the guitars brand so there we go and then after the loop let's have another div element where we will say user input and then we went to output that user input so bear in mind we are not sanitizing anything as far as the user input i want to make that clear we should but we aren't so this could potentially be a very very bad thing thankfully it's not so let's go to the browser let's refresh the page here and we see our list of guitars and then at the very bottom we can see the user input and we can see that the html was not rendered as actual html so the script didn't have a chance to execute because it was html encoded so there's a couple of things that i want to talk about regarding these double curly braces first of all what is inside of the double curly brace is a php expression so that means you have to follow the same php syntax rules as just normal php code that's important because there's times i don't necessarily forget that but there's times that i guess i'm in too much of a hurry and i do have some syntax errors like i might forget to put a dollar sign in front of a variable which of course is a syntax error and you will definitely see an error if you make that type of mistake just like that so just try your best to remember that it is a php expression it can be something more than just a simple variable like we are using here it can be a complete expression the second thing to remember is that it automatically html encodes the output so it is a safe way to output information especially if it is coming to the user once again though sanitize the input because even though blade is essentially saving you by encoding the output that is still stuff that you don't want to store in the database if that is what you were going to do with it so just sanitize your inputs you will be fine as a secondary blade will protect you as long as you output information using the double curly braces all right so that's all well and good but let's also assume that we might call that get data method and not get anything in return it might be an empty array that would represent that there would be nothing in the database so let's write some code that's going to handle that situation so let's comment out the records if you will inside of the array and let's go back to the index so we only want to display the list if there is in fact a list to output so we can wrap this with another directive the if directive it's just like a normal if statement in php to where we can check to see if the guitar's length or the count is greater than zero if it is then we want to show our guitar list otherwise we want to display at least a message saying that there is no guitars or something like that so we will use the else directive there then we will have the output for no guitars there are no guitars to display and then finally we end the entire block with end if so now we have some logic inside of our views if we have guitars we show them if not we show the message there are no guitars to display and once again thankfully blade is protecting us from not sanitizing our inputs but of course if we change this back to where we do have guitars well then our content is going to change we will show the list of guitars and then that message saying that there are no guitars are gone which is of course what we would expect so in the next lesson we are going to implement the show view in this lesson we are going to implement the functionality for showing an individual resource this means that we want to write the functionality for the show method on our controller and we of course want to create the show view to well show that data now when this class was generated it used this id as the parameter for this method and the idea behind that is that this is the id of the record in the database it's a unique identifier so that you can find the unique resource that you want to display and in most cases that is an integer value however it doesn't have to be an integer it can be any type of value as long as it is unique for an individual resource so if that's a string then use string it just really depends upon the type of data that you're working with in our case it is an integer value because each one of our records if you will has an id value so the first thing that we want to do is take this id and search our data for that record that has the id so let's start by getting our data we'll just store this in a variable called guitars we want to call that getdata method and there are several different ways that we can do this i'm going to use the easy way and just use array search now this isn't enough basically what we want to do is say that we want to find the id in the provided array but our array is a multi-dimensional array so what we want to do is search within the individual arrays for the id value of whatever was supplied here so what we can do is go ahead and get the values of all of the columns so we can call array column we will pass in the guitars and then we specify the column that we want to retrieve which is going to be the id so this is going to give us an array that contains just the id values so that we can search that with the given id which is going to give us the index now there are two possible values that we can get by calling array search it can be false if it doesn't find what we're looking for in which case we need to check to see if it's false so we need to use three equal signs here because the alternative is an integer value that represents the index in our data array and if it's zero well that could be considered false so we want to check to make sure that the index that we receive is exactly false and if it is well then that resource doesn't exist and how we handle that is simply by returning a 404 otherwise we are going to return the data based upon the provided index so we are going to call the view function uh we'll call this guitars.js show and then we want to pass in the data for this individual guitar so we'll just give it a key of guitar and then we will provide the data there so that is the guitar at the given index so we can go ahead and implement that view we're going to put this inside of the guitars folder so let's create a new file there we'll call it show.blade.php let's copy what we have for the index view and we will use that as a basis because that already has a lot of the stuff that we want such as using the layout defining the content section and at least it has some of the markup so in this particular case we don't really need to check to see if we have a guitar because if we don't the controller is already going to return a 404 so all we really need to do is display the guitar information and we already have markup for that so let's get rid of the loop we'll also get rid of the if statement and we don't have any user input here so we are essentially going to show what we did on the index but in this case it's going to be just an individual guitar and wow did i mess up that markup so there we go the unordered list should not be inside of the h3 so now all we need to do is link to this view and we can do that of course inside of the index view we do need to fix this markup now so let's move that unordered list outside of the h3 element because we want a link inside of the h3 so this is where we will have our href and we will use the route function in order to generate the url for our resource so let's call route and in this case the name of the route was automatically given to us because whenever we set up the route we called the resource method so by calling the resource method that automatically created named routes for all of our actions on the guitar's controller and in this case it is guitars.show so that is the route name that we need to use but this isn't enough because we also need to tell it what guitar that we want to show so let's go ahead and first of all go to the browser let's refresh the page and we are going to see an error that we are missing the required parameter for guitars.show the url is guitars and then the route parameter is called guitar now this is interesting because if we look at our controller it created a parameter called id and remember that there is a direct relationship between the route parameter which is called guitar i mean we see that right there with the parameter name in our controller so this means that we need to go to our show method we need to change this id to guitar and we only used that value in one spot so we can go ahead and make that change there but then we need to go to the index view and where we are calling the route function we need to supply that guitar value so we're going to pass in an array where the key is the route parameter and then we want to supply the value which is the id and then that is going to give us our url so we can refresh the page now we can see that everything is okay and if we click on any one of these links it is going to take us to the individual page for that guitar so there we have the american standard strat if we click on the talman we will see the tauman guitar there and if we wanted to test the functionality for showing a 404 well we definitely don't have a guitar with an id of 10 so let's try that and we see a 404 as a result so there we go we have implemented showing an individual resource so in the next lesson we can actually get started working with data we'll get our database up and running and we will start creating our model in this lesson we are going to configure our project to connect to a database and the first thing we need to do is make sure that the database is up and running now if you are using xampp or mamp just fire up the control panel and make sure that the database engine is running mine isn't so i'm going to start that i'm also going to start apache because my management tools are web-based now if you manually installed mysql or you used composer then mysql is probably running right now so then the question becomes how do we manage it well you can use the built-in command line tooling if you want to go that route when it comes to working with databases i prefer a graphical interface so i'm going to use a web-based management tool called php my admin it's been around for a very long time now that doesn't mean that it's antiquated and hasn't been updated because it has it works very well it's rock solid and it's my go-to tool for managing a mysql database if you don't want to go that route there are other options you can download the mysql workbench from the mysql website it is free you can download and install it and connect to your database there are many other tools available as well but really once we create our database we aren't really going to be using the tools because everything else is going to be done using artisan so let's go to our project first of all because we need to configure our project to know where our database is so open up the dot env file and we are interested in the settings that begin with db underscore there's a connection which is the type of database that we are going to work with the host which is the machine that the database is running on and its port the database that our project is going to connect to the username and the password now of course most of these are going to be different based upon your configuration but i should also point out that mysql that's just the default there are other options if you go to the config folder and then open up database if we scroll down a little bit we are going to see the different kinds of connections so there's sqlite there's mysql there's postgres there's microsoft sql server so if you wanted to use any of these then you would just use these keys as the value for the db connection and then of course your host import username password settings would need to change based upon your database server so these are supported out of the box so in our case we want mysql my host is the localhost my port is 3306. i believe that is the default and the database doesn't exist but we will create that here in a moment and as far as the username and password for my database engine its root and the password is empty which of course is not secure at all but this is a development box so that's okay all right so we want to create this first app database and we're going to do that inside of our management tool since i'm using php admin that is of course what you are going to see on screen and we are just going to create that new database now we could call this whatever we wanted and then we could change the value in the env file but since the default here is first underscore app which is basically the name of this project we'll just run with that it makes sense and that's typically what i do in the real world anyway if i need to create a database for an application it's usually named after the application so we are just going to put in the name of the database that we want to create and create it and voila we are good to go now of course we don't have any tables but that's okay because we will use artisan to create those tables in the next lesson as i mentioned in the previous lesson we typically don't use our database management tools for creating and working with our tables instead we use artisan to create and run what we call migrations now migrations are really nothing more than a way of versioning a database and it's really not a development tool as it is a production tool it gives us the ability to not only make changes to our database safely but we can also roll back those changes if we ever decide to so really there's going to be two things that we need to do we need to create a migration which is for changing the structure of the database itself so that's creating a table it's adding columns it's things like that we also need to create what's called a model this is the code that we use that actually interacts and works with the data inside of the database so let's look at how we can do that we will of course use artisan and anytime we want to make something we're going to prepend the command with make and in this case migration let's look at the help now at the very least you have to provide a name and most of the time that's going to be it but one thing to be aware of is that your names need to be specific such as create guitars table or if you're going to add a column then you would say add years column to guitars i mean it can get very long but the reason is because it needs to be specific as to what it does because as you'll see here in a few moments there's a lot of migrations so if you're vague in the names of your migrations it's gonna get confusing so just be specific there so that's how you would create a migration let's look at creating a model so the command is make model at the very least you have to provide a name the name of a model is the name of the class that is going to be used so this is much easier than creating a migration now in our case we want to create a table but we also need to create a model that's going to essentially interact with that table so we need to do both of these things they are related to one another so it would be nice if we could create them at the same time and we can by using the migration flag so this is what we're going to do we will use the make model command we're going to call our model guitar by convention our model names are singular nouns so if we needed a table to store people's automobiles you know like cars we would just call it car or if we were building some kind of real estate application to where we needed to store individual properties we would call it property you know something along those lines in our case it's just going to be guitar and then we want to specify the migration flag and then whenever that runs let's go to our project let's start by going to the database folder and then migrations and you can see that there are already some migrations here this is why i said that we need to be specific as to the name of our migrations because if you just name them vague like migration 1 migration 2 migration 3 you don't really know what's going on here so here we can see the create guitars table that was named automatically by artisan because well that's what we're doing we are creating a table so let's open up this file and you're going to see that it's really nothing more than a class and it has two methods the first is up the second is down the up method is for doing whatever this migration is for so since this is for creating a guitars table that's what is inside of the up method now remember i said that you can roll back a migration and that's what the down method is for is to undo whatever was done inside of the up method now a note of caution you only want to undo whatever it is that you did instead of up so in this case this is creating guitars the down method is going to drop guitars if it exists it's not going to do anything else on any other table it's just going to undo what up did and if you try to do more than that you can start running into issues now let's focus on the code that is creating this guitars table you can see that it's using a builder type of syntax we're not really defining columns here we're just building a table using normal php code so the first is id this is going to create a column that contains a unique identifier for every record i am a firm believer in that every table that you create should have an id even if you don't think you need one you need one so just always include the id storage is cheap and ids by default are integer values so they aren't going to take up a lot of space anyway so just include it you'll save yourself a lot of headache later then there's the timestamps and this is a very nice little feature this adds two columns the first is going to contain the date and time that a record was created and the second column is the date and time that the record was last modified and that sounds like a lot of work but we don't have to do it it's done automatically so that's nice to have so let's build the rest of our guitars table because we've been working with this data already so we're going to use this table object here and we want to add a column for the name of the guitar which is going to be a string value so we will pass in the name of the column that we want so let's just call that name let's copy and paste that because we also need the brand of the guitar but let's also include the year that the guitar was made now we could use a string but that makes no sense whatsoever so we're going to make this an integer value because that's what a year is it's an integer and then as far as the name of the column is concerned we could say year but let's say year made now by convention we use an underscore to separate names of course you can follow whatever convention that you want just be consistent in what you do and of course if you needed other columns you can add those there are a ton of methods for building a table we're not going to go through them because we don't have that kind of time so there will be a link in the description for this video that will take you to the documentation of all of the methods that will help you build a table in our case this is all that we need so we're done here so before we run this migration let's look at our model that's inside of app and then the models folder and then there's this guitar.php this is nothing more than a class and it's a very simple class there are some things that we will add to this class but for right now this is going to be just fine and one other thing that i want to point out is that this guitar extends model and if we look at model it's inside of a folder called eloquent eloquent is what's called an object relational mapping or o-r-m this is a very nice way of working with the data within a relational database because at the end of the day what we get to work with is just normal php code we don't have to write raw sql although in some cases you might need to but in most cases you don't so eloquent is the orm that we use to interact with our data and so this guitar is an eloquent model so before we close out this lesson let's go back to the command line and we want to run the migration so if we look at migrate that is the command that we would use to run all of the migrations that haven't been run yet which well there's several there's one two three four and then ours is the fifth so it's going to run all of those migrations but it's also going to keep track of the migrations that have and haven't been ran but really that's not what i wanted to show you let's just run php artisan because migrate has some very useful things such as fresh which is going to essentially drop all of the tables and it will re-run all of the migrations so as you're developing and you find that you just need to start fresh you can use migrate fresh and then that's going to start you over at least as far as the database is concerned but then there's the reset which is going to roll back all of the database migrations or you can roll back just the last database migration in our case we want to just run the migrate command because that is going to run our migrations you're going to see that it ran all of those migrations and if we look at our database management tool we're going to see those tables of course the one that we are concerned with is guitars right there and if we look at this database table there's of course not going to be any data but we can at least see the file structure where we have the id the name the brand the year made the created at and the updated ad columns so in the next lesson we're going to create a form that we will use to create and store data in our guitars table we are finally ready to start working with actual data now that we have a guitars table and our guitar model and the first thing that we need to do is create a view that's going to have the form so that we can submit data to the server and then we can take that information and store it in the database so let's start by going to our controller app http controllers and then guitars controller and we want to implement the create method because this is what is going to be called in order to show our form so all we need to do is return that view and the view name is going to be guitars.create so we can create that view or we can copy it from another view and let's copy it let's use the show because that's going to give us the least amount of stuff that we need to change and we will of course call this create.blade and i am going to paste in the markup for this form because you don't want to see me type all of this out but it's very simple there are three fields the first is guitar dash name that's for the name of the guitar then we have another field for brand and then one for the year now the very important thing here is the name attributes because that is what's going to be used to submit the data to the server that's what the browser needs and there's also some css that i'm going to add to our sites.css file that is inside of public css and then site.css we're not going to go over this it's just adding some rules so that our form isn't going to look completely horrible so with that done we should be able to go to guitar create and we will see our form there it is now of course we could fill this out and submit it but we're not going to be doing anything with that because we need to write that code so let's do just that the first thing that we need to do is add a use statement so that we can pull in the guitar class so that is app slash model guitar and then we want to create a new instance of this class so that will be the first thing that we do we can just call that guitar and here's the idea we are going to assign values to the appropriate properties well our properties are the names of the columns that we created so we have a name property a brand property and then this year underscore made so it's going to look like this to where we say guitar name equals and we're going to use this request that was passed as the parameter to this method this is a lot like the request function that we used all those lessons ago whenever our routes were inside of the web.php file and in fact we could use request here if we wanted but since we have this request object let's just go ahead and let's use that now instead of using this like the request function this is an object and we want to retrieve the input that was provided so we call a method called input and then we pass in the name of the form field that we want to retrieve here which was guitar dash name and then we just need to rinse and repeat for the other values so we had a brand which just happened to be the same name as the form field so we will reuse that then we had year underscore made and in the request that was just year so we are building this object one property at a time and then finally we want to save that in the database so we call the save method on this guitar object and then we're good to go but then we want to do something else we don't want to just save the guitar and then stay there we want to redirect to someplace else and where we redirect to really depends upon our application so we could call a function called redirect and then we could pass in the url of wherever it is that we want to redirect to but you know urls change and it would be nice to have the flexibility of using the route name to generate that url and we can do just that by calling redirect this is going to return an object that has a route method and then we just specify the route name of where we want and i think going to the guitars index makes sense in this case so that whenever we create the guitar it'll take us back to the index so that we can then see all of the guitars that have been created but of course the guitars that we are displaying are all hard coded so instead of calling this get data method that we have we can use our guitar model and we can retrieve all of the records that's essentially going to give us the same thing but of course now we're going to be reading data from the database so in this case we are creating and we are reading that's the c and r of crud so let's go to the browser oh there's one other thing uh let's go back to our create view because we need to specify the action here i did not do that and once again we can use route in this case and then we will simply have the route function generate the url for the guitars.store route so with that in place let's go back to the browser let's refresh so that that is going to change and let's store some data so let's store a starla s2 the brand is going to be prs year made uh it really doesn't matter let's say 2015 and then let's submit and what do we get 419 page expired what what in the world does that mean well we just performed a post request which is supposed to change something on the server and there are other types of requests that do that as well there's update delete and a few others but the main thing is that we are changing something which is useful but it's also very dangerous because requests can be forged an attacker can forge a request to our application and if we're not careful it will execute that request and it could end up completely destroying our application or at least the data that our application is working with so this type of request is called a cross-site request forgery or a csrf it's very common and the way that we prevent this type of attack is including a special form field in our form it has a particular value that the server is expecting and if that value isn't there or if that value is different than what the server expects then it's going to reject that request as i said this is a very common type of attack every language platform and framework has some easy way of dealing with it so laravel gives us a directive simply called csrf that's all that we have to do we need to add this to our form it can be anywhere in the form and that's going to solve our problem so let's go back let's refresh and let's inspect so that we can see that form field you can see that it is a hidden form field and it has a particular value if that value isn't there or if it's different no cigar so with that in place we can now fill out this form so we'll redo starla s2 the brand is prs i think we did 2015 for the year made if we submit this then we shouldn't see any kind of errors but of course we do map model guitar or app model guitar not found well let's make sure that i did that correctly so let's open up models and that's the problem models is plural it's not singular so we need to change that so that it's models let's go back let's refresh we can resubmit this form that's going to be fine so we'll just click on continue and here we are back at the index we can see that we are reading data from the database because now we see starla s2 but we didn't display anything about the year so let's go ahead and let's add that to the index view so that we can put this inside of our list here so that it was made by the brand and it was made on a particular year we'll just call that year made and then we will have the year made listed so we can go back refresh and there we have that well that's all well and good however there is no validation going on so in the next lesson we are going to look at how we can validate the input the first rule of user input is to never trust user input the second rule of user input is to never trust user input we should never trust user input we should always sanitize the inputs which we did not do in the previous lesson we should have done that so let's go ahead and let's strip those tags but that's not enough we also need to make sure that the data that the user provided is what we expect because the user can provide anything and it's up to us to be sure that it meets our expectations like for example they could just submit a blank form now that's going to error out thankfully and it's not going to create a blank record but they could fill out everything correctly but they might have something that is not a year in which case our application is going to fail so yes there is client-side validation but that can be circumvented it's just javascript and there are some clients that might turn javascript off completely so our application that's running on the server is the gatekeeper it is what is accepting the data it's what's storing the data so we need to validate it before we do anything with it so thankfully laravel makes it very easy to validate our data with the request object we have a method called validate and then we pass in an array where the keys are the form field names and then the values for these keys are nothing more than the types of validation that we want to perform so for our guitar name really the only validation that we can do is make sure that we actually have a value because a guitar name can be anything and really the same is true for the brand as well so we would have guitar name then we would have brand and both of those would be required but then we have the year now the year is a little bit different because yes we do need a year but we also need to be sure that it is an integer value so we have two validations that we need to perform here and we can specify that by separating the validations with a pipe character so in this case we want to be sure that the year is in the request but we also want to make sure that it is an integer now an alternative way of specifying that is to use an array which this is what i prefer to use so that each element in the array is the type of validation that we want to perform and there are tons of validation i will have a link in the description for the video you can also write custom validation which we're not going to get into but the key thing here is that for the majority of our purposes the built-in validators are going to give us the functionality that we need so by just validating our input we can go back to our form we can submit this and we're going to see that there is no error it just looked like that nothing happened but in fact something did happen the server did receive the information it did validate it so we need to show the validation errors so let's go to our view and we do that with a blade directive simply called error and we can use this like a function to where we pass in the name of the form field that we want to get the error for but then we also need to use the end error and so inside of this directive we just have the markup that's going to display our error so let's say that we are going to have a div with a class of we'll just call it form error we don't have this class but we will add it and then we want to display the message for the error for this form field and we have a special variable called message it's built in and it is scoped to this particular error so what we can do then is take this error directive and we can paste it everywhere else and then just change the name of the form field so that we have the error for the brand we leave the message alone because once again that is kind of scoped to this error directive and then we will do the same thing for the year whenever we go back to the browser we should be able to just refresh this and it will well no it won't let's resubmit this and then we are going to see the error messages pop up now of course that doesn't look very good so let's open up our css file and let's add that class and we'll make this some kind of child of form and the classes form error let's set the font size to something smaller so let's do 0.75 rem let's make the color red let's also make the font bold so that it kind of stands out so with that we should be able to resubmit this and we are going to see there we go the guitar name field is required the brand field is required the year field is required so if we fill these out we already have a starla let's say a vela s2 and the brand would be prs but let's put something that is not a numeric value for the year if we submit this we are going to see all of the errors for the guitar name and brand go away but we see that the year must be an integer but also notice that we've lost the values for the fields that were good so what we can do then is use a special directive well it's not really a directive it's a function that will get us the old value for that field so for each one of these fields we're going to use the value attribute and we're going to call this old function and then pass in the name of the form field so in this case it'll be guitar name and then let's just copy and paste this wherever we need to for the brand we'll change it to simply brand and then of course the year will be the year so now let's go back let's fill this back out so that we have the vella s2 the brand is prs and then once again we'll have something other than an integer value whenever we submit this those values will be retained and um yeah we didn't change that old value to year did we so there we go if we submit this we're going to see the same thing but now we can change this so that let's say 2016 for the year and whenever we submit this then everything is going to be validated it is saved into the database so handling user input is actually very easy we simply use the validate method to validate the user input we specify the validators that we want to use and laravel does the rest if it encounters any validation errors then we can simply display those using the error directive we specify the field name that we want to display the error for and then the message and of course we also want to repopulate valid fields with the old value so we use the old function to get that value but of course once validation passes we are good to go we can store that information in the database so in the next lesson we are going to look at how to edit our data it's actually very similar to saving editing is very much like creating we are working with the same data we are almost doing the same exact processes there's just a slight difference between the two but other than that they are the same so there's going to be a lot of copying and pasting so let's start by showing our form now well actually we should start with the show method because this is still showing the data that is hard coded so let's do that let's go to the individual page of the guitar we can see that that is not right so here's what we can do we can fetch the data from the database using our guitar model there's a find method that we could pass the id to and then it's going to find the record with that id and then we would have a record then we could check if it existed and if not then you know we get a 404 otherwise we pass that record on to the view that's fine an alternative is this find or fail it's almost the exact same thing except that it is going to automatically fail and return a 404 if it can't find that record so in fact we could inline this so that our show method is going to be very very clean so there's nothing like code that works except clean code that works so there we go we have that same exact functionality if we go back to the browser this is of course going to show data from the database except that it's not because that was a syntax error but now we can go back and there it is we do need to add the year there because since we're going to be editing this information i want to be sure that we show all of the information that we have so actually we could copy this from the index view and we could paste that inside of the show view and that will be fine for our edit action method we can essentially do the same thing except that we want to display a different view we want to display the edit view and we need to change the parameter name to guitar but other than that that's going to be fine now our edit view is going to be a copy of the create view because remember this is the same exact data so the create form is already there ready for us to use we'll just copy it and use it as a basis for our edit form now we don't want to display the old information because that was what the user typed into the form field after they submitted it the first time and validation failed instead what we want to show is the data coming from the database so we are going to be working with the guitar that is passed to this view and i'm going to use object property syntax here we could use the associative array syntax if we wanted to that's what we did inside of the index and show views however just to show you that we could use this other syntax i'm going to use object property syntax of course in your applications pick one and stick with it consistency is very important all right so we will have the name we'll have the brand and then finally the year made and for the most part that's it we do need to change how this form is submitted because it is currently being submitted to the guitars store route we want the update route but we also need to supply the guitar that is going to be updated so we need to include that that is coming from the guitar object and we can provide the id there and that is the completely wrong syntax we want arrow there but that's going to give us the correct url the other thing that we need to change is the method we want to use a put because put requests are for updating data however browsers don't understand put when it comes to a form submission it only understands get and post so we have to emulate a put request by using a blade function called method we pass in the http method that we want to emulate and then we're good to go so even though this is an actual post request our application is going to accept the request it's going to see that we want to emulate a put request and it's going to route it to the update route so everything is going to be just fine so if we go to slash guitars slash id slash edit we should see our form and we do if we go to the guitars slash two slash edit we should see that other guitar if we go to slash three which does not exist we should get a 404 and there we go so we are good to go there so now we just need to write the code that's going to handle the submission and for the most part we can almost copy the exact same code from the store method and use that because we still want to validate the user input we are still going to need to assign values for name brand year made the only difference is we need to fetch the guitar from the database as opposed to creating a new guitar so we are going to copy this entire thing and we're going to paste it inside of our update method and instead of creating a guitar we are going to fetch it from the database but once again we are going to use this find or fail because if the record doesn't exist we don't want to do anything we want to 404 there so we do need to change the name of this variable because guitar is the parameter with the id so we're going to use record here and we're going to save it as far as the redirection i think it makes more sense to redirect to the show route but we also need to supply the id and we can do that with just the guitar there so now let's just test this and make sure that it's actually going to work so we could edit the name let's also edit the year but remember that the year has to be an integer value so let's do something that's very different to 2000 so if we submit this we should be taken back to the page for that guitar we can see that the name is different so we can see that the year is different so we successfully updated that data now as i mentioned at the beginning of this lesson there's a lot of repetition because these processes are almost identical so in the next lesson we are going to start to see how we can eliminate some of that duplication we have some duplicate code inside of our controller and i wouldn't say that our controller is messy but this duplicate code does add well quite a few extra lines of code and it would be nice if we could clean this up just a little bit because i am a firm believer in having clean and concise controllers because that just makes maintenance so much easier so the first thing that we are going to look at is essentially this right here where we are trying to find a guitar from the database if we find it then great if not then it returns a 404. we do this in three places and really we would do it in four if we implement the destroy method because we would want to make sure that the given id exists in the database before we actually try to delete it and the way that we can clean this up is just by using our model guitar as a type hint for the parameter because layer laravel then is going to take the id that is given to us from the url and it is going to automatically try to find that guitar in the database if it exists then great we have it if not it will automatically fail in return of 404 so we can eliminate that code very easily so let's just do that we will use a type hint for the show the edit and then the update method except that update is going to be a little bit more involved because we need to change the name of the variable that we use we are no longer going to be using the record variable because we will have this guitar and then the id will need to be used for the redirect and there we go now we didn't really save a whole lot there but at least it's a little bit cleaner besides the bulk of this controller is really the store and the update methods we are essentially doing the same thing where we are validating the user input and then we are updating the values of the properties of the record that we are either creating or updating and in the process of that we are stripping the html tags so it would be nice if we could do all of that in kind of one place so that we aren't repeating ourselves well we're going to have to repeat ourselves somewhat but we could eliminate that repetition because we have this request type here and we can actually build our own custom request that would then be used for handling our guitar form requests so let's go to the command line we are going to use artisan to make a request and we're going to call it guitar form request this is going to generate a new class for us that is going to allow us to not only validate the information but also work with the request data before we validate it because it does kind of make sense to go ahead and strip out all of the tags before we validate you can make arguments for either approach it really doesn't matter what does matter is that we can do this all inside of this class this is inside of app http requests that was not there to begin with but it is now and then there is our guitar form request now by default there are two methods there's authorize and rules now this is returning false for authorize and this is going to mean that we are not going to be authorized to make this type of request so the first thing we want to do is return true here now of course if there was a need to make sure that the user was authorized then the code necessary would be inside of here but we're not going to worry about that we're just going to return true because well we want to authorize ourselves to make this request and then we have this other method called rules these are the exact same rules that we do inside of our validation code in the controller so we can just copy and paste there and that's going to give us the exact same thing however i also want to go ahead and strip out all of the tags so that we don't have to do that any other place and we can do that by implementing another method here it's going to be a protected method called prepare for validation and what we want to do is take the information that we are working with and merging it into this object basically that we are working with so we have a method called merge so if we needed to include another form field that didn't come from the user like for example if we had the code for user authentication and we needed to supply the user id then we could do that very easily by just merging that in here but in our case what we're going to do is essentially overwrite the values that we have as far as the guitar name and the brand and the year so that it would look like this to where we are going to strip the tags here and then we are going to work with the data that's coming from the request so in this case it's going to be this guitar name then we will do the same thing for the brand so that we will strip the tags out of that input field in this case i'm going to use just the object property syntax the only reason why i'm didn't for the guitar name is because well guitar name is not a valid php identifier but brand is as well as years so we will essentially do the same thing that we did for brand so we are taking the existing data from the request and merging that in so that we are essentially overriding those values by stripping out in the html tags and that's automatically going to be done for us so that then all we have to do is use this guitar form request inside of our controller let's first of all import that we need to use app that's http requests and then the guitar form request then for the store method you know it's already being type hinted as request we're going to use a guitar form request and then we are going to do this we will have our data but we only want the validated data so we're going to take the request and we're going to get the validated data now there's a difference between validated and validate validate is the method that we just replaced we want the validated values so that then we can use them whenever we assign the name brand in year made so with a few modifications that's all that we are going to do and then we just need to do the same thing for the update method so let's just once again copy and paste as i mentioned we can't completely get rid of the code duplication but we can make it easier to work with so there we go with that done we can go back to the browser let's go to the edit field and i guess i better make sure that i did save that i did okay so here is the edit for the first guitar let's first of all clear out the guitar name and let's submit it we should see the error that says that this is required although no it wouldn't validate it does not exist why does it not exist and that's because i did not use the guitar form request so that's kind of an important piece there so let's refresh we will continue so that we resubmit the same information and we can see that the guitar name field is not required now it automatically filled back in the data from the database that's fine so we're going to change this back so that it doesn't have the edit value we can also change the year made i believe we had 2015 originally we can submit and that is going to work just fine but let's also try creating so if we create a new guitar then this can be what we can have an explorer which is made by gibson and the year can be 1977. so we will submit that we should then have three guitars in the database we do and while we still have some duplication our code is indeed cleaner and easier to understand we can also use mass assignment to clean up and simplify our code there are however some issues that we will need to discuss but first what is mass assignment well whenever we have created or updated a record in the database we have done so by assigning the columns individually we are being very explicit as to what we are setting and then we are saving that record that is individual assignment mass assignment is doing all of those things all at once so the code to do so would look like this in order to create a record we would use our model class it has a method called create and then we would just pass in the data that we needed to create that record and that's it we no longer have to set name brand year made or save or anything like that this one line of code will do all of that for us and the same is true for update so if we look at the update method we still need to use our record object that we have in this guitar variable but we would call an update method we would once again pass in the data that we wanted to update and that's it everything else is done for us that is mass assignment so the first thing about mass assignment is that the data that we are passing to either the update method or the create method needs to have keys that are the same names as the columns in the database like for example we have name in the database but our form has guitar dash name the database has year underscore made and the form has just year so in order to use mass assignment we need to change the field names in our forms so that they match the column names that's not that big of a deal so we can go ahead and do that now as you're doing this don't forget to change the values of the four attributes for the appropriate labels that was for the year made well it's now year made and for the name let's do the same thing inside of the edit view and we also need to change the guitar form request class because we used these form field names there and we did so really in two places if we look at the rules we need to modify those field names so that we have name and then year made but when it comes to prepare for validation we need to do the same thing now since we just have a name property now we can use the property syntax and then we will change year made we also need to change the keys here to match but that's going to make everything work so with these changes in place we should be able to create and update these records so let's go ahead and let's try that let's go to the create form and let's add a strat because we don't have one yet the brand is fender and the year made let's just do 2021 and whenever we submit this we are going to get an error and it says add name to fillable property to allow mass assignment so here's the thing about mass assignment it's very dangerous you are taking the request data and even though we are validating it which is very good but we are just kind of blindly passing that on to the update and the create methods saying here database take this information and create or update a record and that's really not a big deal for the data that we are working with but imagine that you are building a system that is working with some sensitive information like user accounts and while you are validating that information you aren't really checking everything maybe the user supplied some extra fields in the request that would then be populated in the database if there was a matching column name there's a lot of things that can go wrong with mass assignment so it is something that we have to opt into and if we look at this message again it says add name to fillable property so what this means is we go to our guitar model and we are going to add a property it's a protected property called fillable and this is simply an array that contains the columns that are okay to mass assign in our case that's just about every one of them so that means name brand and year made but if we left any one of these off then eloquent will not allow that column to be assigned a value using mass assignment we would have to do so explicitly like we did before by assigning a value to that column but as i said the data that we are working with is okay to mass assign there's nothing sensitive nothing that's going to break or cause some kind of vulnerability within our application so now we can go back let's refresh and we'll just hit continue here so that it will resubmit that form and then everything should work we should see our list of guitars and here we can see the strat that we added and of course if we wanted to test the editing of that all we have to do is go to the edit form for that guitar let's add edited to the name and then we will submit and once again we are going to see that that works because now that we set that fillable property in our guitar model this works for creating and updating it's a one-time set thing so there's nothing wrong with using mass assignment just be very careful when you do so if there are columns in your database that control how the application behaves or controls a user's access to certain parts of your application don't make those columns fillable it adds a little extra work on your part but it makes your code much safer laravel is a fantastic framework and it's no wonder that it has become the go-to application framework for php it's my hope that by now you have a solid foundation in the fundamentals of building laravel applications but of course we've just scratched the surface now that you have gotten started with laravel you can dive deeper into the framework and you'll learn something new every time you start developing a new project i highly recommend that you spend some time reading the documentation it is very well written and highly informative but it can also give you some insight if you find yourself hitting a brick wall laravel also has a fantastic community ready to help for whenever you need it just remember that no matter what type of issue you face someone and perhaps everyone has faced it too and we are more than happy to help thank you so much for watching this course please feel free to contact me through twitter or the touch plus forums if you have any questions from all of us here at tutsplus thank you and i will see you next time
Info
Channel: Envato Tuts+
Views: 111,494
Rating: undefined out of 5
Keywords: get started with laravel 8, laravel 8, laravel, laravel tutorial, laravel full course, how to learn laravel, learn laravel step by step, laravel 8 tutorial for beginners, laravel tutorial youtube, laravel 8 tutorial, php laravel youtube, laravel for beginners, laravel tutorial for beginners, laravel project, laravel 8 lesson, laravel setting up, laravel 8.0, laravel v8 setting up, laravel 8.0 tutorial for beginners, laravel 8 installation, php, envato, envato tuts+
Id: AGE3wRKljkw
Channel Id: undefined
Length: 143min 44sec (8624 seconds)
Published: Wed Dec 15 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.