Laravel PHP Framework Tutorial - Full Course for Beginners (2019)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Welcome, everybody, my name is Victor. And we're gonna be tackling some Laravel. And we're going to do a full course on Laravel from scratch. But before we even get to that, I want to show you what we're going to be building. So for this project, we're going to be building an Instagram clone. And it looks pretty much just like Instagram. So if we click on a post, we'll be able to follow, we'll be able to unfollow, we'll be able to edit profiles, we'll be able to change our profile image, we're going to be resizing images from scratch, using the intervention library, you're also able to add a new post, of course, you can write your own captions, choose your image, we're also able to log out and have users and authentication, we're able to register users, including their username, just about everything that Instagram can do, we're going to be able to do and I'm going to show you how to do everything 100% from scratch. So this is going to be a full fledged course, there are no slides here, we're going full on board coding, with zero breaks, we are going straight through learning every single minute. So if you stick with me, I promise you, I'll make it worth your while. And you're going to learn a ton about Laravel. So what is Laravel? Well, if you're unfamiliar, Laravel is the fastest growing open source PHP framework to date. As a matter of fact, it is the number one framework in GitHub. And it has allowed the community to by far write some of the best PHP applications to date. It is extremely easy on newcomers. But it is extremely powerful. You can certainly do anything from a small project to a huge Enterprise Project. And it has a fantastic community behind it. Now throughout this course, I am assuming that you have general knowledge about PHP, and how to set up an environment for you, I'm just going to run you through the very quick installation steps to actually install Laravel. So with all of that, let's just get right to it. We have a lot to cover, and we don't have any time to waste. So how do we install Laravel? Well, the easiest way to install Laravel is using the Laravel installer. So I'm going to jump back to my terminal. And now in my terminal, the first thing you need to make sure is that you have composer, composer is a PHP dependency package manager that you're going to need. So composer, PHP package manager, we can do a quick Google search for it. And there it is. So get composer.org. So if you visit the getting started, I recommend you go ahead and follow the instructions to install it globally. to actually install it, all you actually need to do is run this command right here in your terminal, and then just make sure that you follow the steps to install it globally. So those are the steps. Once it is installed, you should be able to run composer and you should be able to get something like this. So if you did everything correct, you now have composer, what else are we going to need to make sure that we have the next thing is we need to make sure that we have node.js and that is node j s.org. Now node j s is made for every single operating system, you can simply just go to the download section here. And there you go. We have windows, we have Mac, we have source, you could do just about anything. Once you have node installed node also installed NPM. And NPM is actually the JavaScript counterpart to composer. So we should be able to run node dash V, and get a version number, and NPM dash V and also get a version number. So with that, the last thing we need is that Laravel installer. So if we go into documentation, and we scroll down to installing Laravel. Now that we have composer, we can run this command, we can run composer global require level slash installer, what that's going to allow us to do is be able to run something like Laravel. Now if you run level, and this doesn't come up, even though you ran composer, it means that you don't have your composer that been in your path directory. So if you echo out path, like so, you should have composer somewhere in here. In my case, it is slash users slash Victor composer vendor bin, do a quick Google search on how to add composer to your path. And you'll find it just for your system that this does vary from system to system. So it's not really worth showing you how to do it one time. Once you have that done, you should have level. So let's jump right to it. Now that we are ready. So the first thing I want to do is I want to show you what we are currently working with. Let's go to instagram.com slash Free Code Camp. So here we see what we are trying to replicate. So we're going to be going back and forth to this to get exactly what we want. of our page. So first and foremost, I'm going to start with this header up here. So now let's create a new level project. I will say Laravel, new, Free Code, Grant. That's where a project name is going to be. Let's let it do its thing. And there we go. So we can CD right into Free Code gram. And we are in our project, I will open this up and PHP storm. Alright, and there we go. Now at first glance, when we open our project, there are a lot of files here. Now the first thing I want to let you know is, don't worry about the fact that there are so many files and directories and all of this, throughout the project, we're going to be touching up on a couple of these. And to be honest, over time, this becomes second nature to you, and you'll know exactly where to find everything. But just don't let that overwhelm you. The first thing I do want to show you though, is of course, we have composer, but there is this composer dot JSON file that I've spoken about. And this file is the file that would basically hold your projects assets. What I mean by acid, of course, is we do have composer, which is going to be our dependency manager, but composer itself needs instructions. And that's what this file is for. Let me go ahead and close these extra warnings that I'm getting here. So we have our file. And a lot of this stuff you're never probably touch. Now we will talk about how to add things to require and things like that. Don't worry about any of that. But just know that whenever I talk about the composer, that JSON file, it's right here right at the root directory. Great. So now, the first thing that I want to show you is I want to jump back to the terminal. And let me clear this up. So the very first thing I want to show you is artisan artisan is a command line tool that ships with Laravel that allows you to do a ton of different things for your application. As a matter of fact, you can interact with your entire Laravel application through artisan using something called Tinker, we'll get to that. But what I want you to notice is throughout the course, you'll see the exact directory that I'm running any command right up here. So always make sure that you are in the correct directory. So inside your actual project directory, I'm going to run php artisan. And this is going to output a bunch of different commands that are at your disposal. Now let's go back all the way to the top right here where it says available commands. And we can consider these the root level commands that you have. So these commands, you only run with php artisan. After that, they are basically namespaced commands that you can run like in the app namespace, you have app colon name, off, off, colon, clear resets, and so on and so forth. Now, it might seem super overwhelming that there is all this stuff here at your disposal. But no worries again, just one thing at a time. The very first thing I want to talk about is authorization. One of the reasons to use a framework like Laravel is to basically rocket your development into developing exactly what you need for your application, as opposed to spending time developing things that you don't quite need. So we're going to be talking about make off. But before this, how do we actually view this page in our browser? Well, that's actually quite simple level ships with a built in PHP server that we can use. And that is this command right here. Now to run a php artisan command, you will run php artisan, and then the command name, in our case is surf. Alright, let's try that now. Inside our project, we'll run php artisan surf. And now it tells us level development server has been started and it gives you an address. So we can copy that address. And let's head to Chrome. We'll add a new tab on here. And let's go to this page. And there you are. So this is our project. So that's pretty cool. Laravel does ship with a nice development server, you can run that in the background, and basically just leave it there. And I'll show you how to do that. So right now we're obviously in this tab. And we do see here that there was a 200 requests that just happened. Obviously, that was us when we loaded the page. Now in most terminals, you can run up here somewhere and create a new tab. So I'll do that now. And what I will do is I will CD back into that same directory. So I'll say SEO, it's a little shortcut that I have, and then Free Code gram. So we are back to exactly the same place we are inside here. You have to leave this running here in the background. That way your page is served in the browser. Great. So we'll keep going. And I'll take it as slow as I can. But we have a lot to cover. So we need to kind of keep it moving a little bit. So let's go back to PHP storm. Let's close our composer that JSON file. And the first thing I want to show you is well this page right here, obviously we are loading some sort of page It says level and it's got a couple of links right underneath. So where would you find anything related to HTML? Well, Laravel makes it very simple. If we go to resources, and then we go to views. Now we have this welcome that blade that PHP. Now that blade syntax, we're going to talk a little bit about blade up front. blade is a rendering template. And what it will allow you to do is be able to throw in snippets of PHP in your views without it feeling like you are hacking away at your views. Because your views will primarily be composed of HTML markup, there should be no reason why you should ever be computing or fetching database queries or anything like that, in your view. That's what your controllers are for. We'll get to that. So here we have this page. And if we scroll down some, sure enough, we see Lenovo. And then we see a bunch of our links. Great. So let's change this from level to free code, Grant. It save, go back, hit refresh. And there we are. So we are successfully changing that page. Great, I do want to get right to work. But before I do, I need to do one more housekeeping issue. The thing is that Laravel ships with an authentication system that allows you to register users, it allows you to log in users and keeps track of all your sessions. It does all of this for you out of the box. Now this command, even though it's a little early to introduce you to it, we have to run it because it will change your views, meaning it will change this page that we're working with. So for now, just trust me on this one, let's blindly run PHP, artisan make auth. And when we do that, and head back to PHP storm, we now see that we went from one file called welcome. And all of a sudden, we have this off and layouts. In home, we have a lot more files here inside this views directory. And furthermore, if we go back to Chrome, and we hit refresh, if you noticed up here, now you have this login and register. So that's exactly what I needed, I wanted to make sure that we were set up with an authentication because of course, in Instagram, you will be able to sign up and login, just like you would expect. So basically, what I just did with that command was set that up for us. And that's great. That's one of the key features of Laravel to get you up and running right away. Awesome. So now that we have that, let's go back. So what I want to start doing is, I want to get started in developing some of these views, before we even jump into the level section, because that's really going to help us to facilitate through this project that we're going to be working through. So to do that, what I want to do is actually fire up the JavaScript section of Laravel. One of the most powerful things about Laravel is that it is a full development framework, meaning it does have opinions about your front end just as much as it does in your backend. So Laravel ships with a working implementation of bootstrap, that's Twitter Bootstrap, which I'm sure you're familiar with, and view. Now Vue. js, is a very easy to get started JavaScript framework that will allow you to do all of the things that a modern application needs to do. Now, the best news about this is that Laravel ships ready to go with this already in it. However, we do need to run a compilation. If you're not familiar with modern JavaScript development, one thing you may not be familiar with is NPM. So a lot like what we talked about with composer NPM is a package manager. But for JavaScript, remember, you're gonna have your front end, and you're gonna have your back end, for your front end, we're gonna use of course, HTML, a little bit of JavaScript, view, all of those things. And then for your back end, of course, we have PHP, and then layer those running on top of that, so kind of start to put that picture together. So what is front end Woodford, the front end, this is our front end, right? Obviously, everything that a user can physically touch. Now, when I touch this button, and I click on it, it goes to my back end, my back end will do something. And of course, it comes right back to my front end. So that way, we know exactly what we're talking about when we're talking about front end development versus back end development. So Laravel, like I said, it is a mixture framework, it will have a bit of front end and a bit of back end, and it is opinionated about both of those. Now, with that being said, As a side note, if you're more familiar with things like react, or jQuery or anything like that, there are ways for you to switch out of view and rip everything out and start over with jQuery, or any other framework in the JavaScript world that you would want to use. So don't worry about the fact that view is what it ships with. You, of course, have the possibility of changing that out and doing exactly what you want to do. But we're going to stick with view. And we're going to stick with bootstrap. And if you want to learn a little bit more about that, of course levels documentation page is the best source for that. So let's get started with this front end stuff. So if you run NPM dash V, you should get a version number. In my case, right now I have 6.9. And if you run node dash V, then you should also get a version. Now, typically NPM and node go hand in hand. However, if you don't see versions of those, let me jump back to Chrome. And let's navigate to node j s.org. And here it is. Now there is a nice installation package for node j s, you can simply just download this, double click it install it, it's very simple, just make sure that you download the one that is correct for your system. And as you can see, here, it's built for every single system, so it's fairly easy to get started with. So that's a little sidetrack, a little bit more setup that we got to do. But once you have that installed, and we have this NPM, we actually have some NPM commands that we can run. But before we can do that, of course, the same as composer, we need to pull in these dependencies. So we're gonna say npm install. Now, this is going to take a little bit of time. So I'll fast forward to when it's done. But don't worry in your machine, it will take a couple of minutes to get started. So there it is, that's done. So once it's done NPM in front end development is one of those things that you need to compile before you can use. So to run a compilation, you're going to run NPM run. And then we have a couple of different options. The first one I'm going to run is just def. So NPM run def. And what this is going to do is it's going to take, what this command will do is it will take everything that level ships with and it will compile it down to a file that we can actually use. Now, the reason for doing this through Webpack is that Webpack is able to take all of this code that you're going to bring into JavaScript, and we are talking about quite a significant amount of code. And then it's going to compile it all down into the smallest minified file that he can find. Now, you may be used to just pulling in some packages through a script. But remember, in a framework, we kind of want to follow all of the best practices. So now that this is done, it does say please run mix again. So let me do that one more time. So NPM, run, Dev. and with any luck, we'll get this to compile. And there we go. Now if you ran into any issues with this step, because they could be a little bit tricky for NPM, depending on what your error is, if you do some Google searches, what you probably find is that deleting the known module, and then installing everything again, typically the second time around, everything kind of works. So just try that first delete your node modules file, and then see if that will fix the error. However, there are many errors that you can run into. So make sure that you Google the correct error that you're getting. But with this being said, what we've now done is we now have this app dot CSS and this app that j s. So Laravel has compiled all of our front end assets into these two files, obviously, one for JavaScript, and one for CSS. Let's check out those files. Let's go back to PHP store. And let's go into resources, again, j s. And then we have this app that j s file here. But this is not the file that it compiled. This is actually the file that we can edit, if you go to public, and then you go to J s. Now that is the correct file. If we load this file up, it might take a second. But once it loads up, you see that this file is not your regular JavaScript file, right, a lot of magic happened to this file. And it is not your typical file. So we're gonna go ahead and close that you would never touch this file directly. The one that you would be working with is the one inside your resources directory. However, I just wanted to show you that the compiled files always end up inside this public directory. So inside this resources directory, we have this app, that j s file. And this file, of course, is the file that did get compiled a little bit more on that a little bit later. But you also do have this sass directory. And inside here, you have this app that SCSS. And this is the file that you mostly be working with. For your CSS, you can add as many of these as you want. All you have to do is make sure you import them something like this. So you see this variables. Obviously this belongs right here. It's loading this file. Great. So now that we've done all of that setup, let's go back to our view. And in our view, let's go to home. So home is what gets loaded when a user logs into our application. However, right now, no one can really log into our application because we haven't created end users. Now to create a user, we do need to have a database setup. So with that, let's go back to php artisan and see what we can find. So if we go to php artisan Then we see we have this concept of migrations. Now, migrations are files that describe your database. So instead of you going into the database and making a bunch of changes to it, and then you having to go to your production server, and make those same changes manually, you're going to write these migration files that are going to describe your database. Now, this is a little bit of a higher concept. But just think of a migration as a file that holds all the instructions that you need to tell your database to create itself. And so throughout this project, we're going to modify the database, but through the migration, not directly into the database. Now, why would you do it this way? Well, the answer is fairly simple. It describes each change in a very systematic way, you know, if you were to just go into your database and make some changes, unless you document those very, very well, more than likely, you're gonna forget to run a step or two in your production, and then everything blows up. Furthermore, any other developers working with, you are not going to know how to recreate that change. And so that is not great for teams. So things like migrations are one of those integral parts of working in a team, because it allows everybody to have the same definition of what the database is supposed to look like. But in order for us to run this migrate command, we need to set up some sort of database with Laravel. So I'm going to be using SQL lite for this project, just because of how easy it is to actually set one up. So I need to create a file, right, and this file is basically going to be a flat file database file. That's how SQL lite works. So to do that, now, if you're on a Mac, you can use touch. However, just to keep it compatible with Windows, let's run vim, and then let's create a new file inside the database directory. And let's call it database dot SQL Lite. Hit enter. And then we're actually just going to exit out because we don't need to write anything to this file to exit out, press escape, then colon, w, q, hit Enter, and you're out. So now we have an empty file inside here. Alright, so let's take a look. If we go into our databases, and right here, we have this database, that SQL lite file. Now of course, PHP storm doesn't know what to do with it, it doesn't matter, we don't need them to know. So now let's go into a new file that we haven't explored yet. And it's this dot E and V file, the dot E and V file will hold all of the different configurations that are specific to your environment. And that's what E and V stands for. It stands for environment. Right now we have a local environment setup. And of course, you can have a staging environment, you can have a production environment, you can have as many environments as your team needs. But for now, all we are interested in is the database setup section. For this project, like I said, throughout this course, I'm going to be using SQL Lite. So we can actually delete all of the DB lines, except the one called DB underscore connection. Now by default, it's going to try to use my SQL. But let's just use SQL lite, and then go ahead and delete any of the other lines that start with DB underscore. Perfect. Let's hit save. And now let's talk about this migration thing. So how do we actually get the database migrated? meaning how do we get it to the latest state possible. But with that, of course, we're going to use a php artisan command. So let's run that now. php, artisan, migrate. And if you did everything right, you're gonna see that all of a sudden, we created a user's table and a password resets table. Of course, the users table is the one that's going to hold users in our application. And our passwords table is a table that will hold any password resets, meaning when somebody forgets their password, they will click on the forgot your password link, that will send them an email. And then that is stored in this table. Again, hold this shift with Laravel. So you don't have to worry about creating a forgot your password, or anything like that. That's already done for you. And that's the beauty of this. So let's move on. Let's go to Chrome and create a new user. I'll say register. And let's say for name, I will just use test user email test at test Comm. And then password, we'll just put a random string here if passwords and click Register. So we land on this error. Now the reason for this error is that you actually need to stop this process right here. Whenever you make any changes to your EMB file. If you make any changes to this file, you have to stop the server and Buddha backup. So it's great that we ran into this issue because it's something you are going to probably run into. So to stop this process from running Of course you can exit out and Come back in. Or if you hit Ctrl C, that stops the process. And then we can run PHP, artisan serve one more time. And we're back up and running. So let's go back to Chrome, hit refresh. And there we are. So we are logged in, check this out, we now have this test user. And we can log out. And we can log back in. Let's do that sequence now. Test a test Comm. Let's put in the password, you do have a remember me. And you do have your forgot your password, login. There we are. So we are logged in. Now let's check out if it's really working. You see this home slash home right here. So of course we can access this. If we were to log out, let's try to access that now. slash home. Nope, it says no, you need to log in. So all of this has been set up for us. Because we ran that make off command. That's very powerful. Let's jump right to it. Let's copy some of this design stuff that Instagram is using. So we can get started with our app. So of course, right up at the top here, we do see some sort of logo. And then we do have the words Instagram, let's try to replicate that in our application. Now, up until this point, everything we've used has shipped with level, we actually haven't written anything just yet. It's all been kind of setup leading up to this point. So we are ready to get started. Let's go to views and then go to layouts. And then you have this app dot blade dot php file. Now inside this file here, you do have this level. And that is what's actually being passed in. Now it is diving into the configuration. So I will actually grab the entire line. And I'm going to change that to free code Graham, hit safe. Back to Chrome. There we go. So we were able to successfully change that up there. Awesome. But now the other thing is we do have this logo, I will actually grab the Free Code Camp logo and splice that in here. So this logo, I do have it as an SVG file. And I will provide this for everybody who's going to be running through this course. So go ahead and grab your file now. And I will actually just paste it into a new document right here. So we can go to our public directory, right here. And then inside public, let's create a new directory, new directory for SVG. And inside that SVG, let's create a new file. And I'm going to call it free code, Camp logo, dot SVG. And here's my file. If I hit save, there we go. So we do have our file here being rendered properly. Now it is a little grainy, but that's okay. This is an SVG file, we know it is the file of the highest quality. So let's do something here. So we have Free Code Camp. Let's wrap this in a div. And let's create another div here. And it's going to have an image. And the source is going to be slash SVG slash, Free Code, Camp logo, dot SVG. Now, notice that I am not appending public. The reason for that is that level actually starts in public. So whenever a user is accessing our site, they're actually inside this public directory, they don't have access to anything outside of the public directory. So we never have to prepend anything before our path. This will simply have our logo, it's just hit save and see what we get. Hit refresh. And there we go. So we are getting this logo, it is a little large. So let's fix that. Now, let me change this from Alta style. And let's say max height, let's give it a height of 25 pixels. See how that looks. That looks about right. But now they are on top of each other. And if you go back here, of course, they're supposed to be next to each other. So easy fix for that, we can change this to a Flexbox. So we can say display a flex, and then we hit refresh, it disappears. And I bet you what it is, is because we used max height, let's actually just change that to height. And I think that will fix it. There we go. Alright, so we have that now we need a little bit of spacing to the right of it. So let's add a class of padding right? Maybe three. Let's try that. Okay, that's not too bad. And then maybe let's add a little bit more on this one. We'll say class padding left of three. Hit refresh. But we're still missing that divider line right here, right. So we can actually do that fairly simple. You can pick one, I'm just going to do the logo. Let's add a border, right. one pixel solid. And let's just go with a really dark gray, maybe 333. Refresh. There we go. So we have our navigation. Now right away, you do notice boom. strap is a little bit wider than the actual Instagram layout. But that's okay, we're not trying to replicate the front end, we're trying to replicate the functionality. So I'm not too worried about that. Now, one thing you do notice here, though, is that if we actually look at where this is lined up, Free Code gram is almost too high, right? It kind of needs to be a little bit lower. So yeah, that is not quite lined up exactly how we would want. So we can just push that down a little bit, we say maybe padding top of one. Let's see what that looks like. That's a little bit lower, but it's still not perfect. Now, one thing we can do to fix that is adjust this logo a little bit, if we make it a little smaller, it's not going to be as noticeable. So maybe let's bump this down to 20 pixels. Let's go back to Chrome, hit refresh. There we go. I think that is going to work out just fine. Anyway, like I said, we're not super interested in the front end, we just want to get to a point where we can actually work. So let's take a look at this front end. So what I see here is you have one box here, and then you have another section here. So we can say that this section here is probably roughly about a quarter to maybe a third of the page. So let's start working that into our project. We do have this level here, we do have this dashboard. So where do we find code for this dashboard thing. Let's go back here to PHP storm. And then let's go into resources views. And then you do have this home that blade that PHP, and that is that dashboard. So let's get rid of that altogether, because I do want to start from scratch on this. So we have a container. And of course, we're going to need a row. And inside that row, let's try having a column of let's say three. And then let's have maybe another one, that's going to be column of nine, right? That's assuming that this is three columns, and this is nine columns. So let's start with this image. Let's try to grab this image link right here. copy image address. Let's go back here. And let's just paste this image in Image Source paste. It's a really long address. So let's just see what happens. Let's go back here, hit refresh. Okay, well, that's pretty good. However, this image is rounded, and ours is square. So there is a class for that, in bootstrap, that we can use in this do that net, we can run the class of rounded dash circle, there we go. So rounded that circle will probably give us a circle. There we go. Alright, so that's working out pretty good. So now what else do we have? Well, we do have quite a bit of padding right here. And then we have quite a bit of padding on the on the right side and looks like the top as well, which we don't have any right now. So let's add some padding to that. So we'll say that this needs maybe a padding all the way around of five, that will be p dash five. Let's see what we have now. Okay, that's looking better. And then we have this right section here. So let's copy some of this text. Now what I will do is, obviously, this is one div, this is another div, I'll make this, this small one here, a div, and then we'll have this section here. That's another div. And then we have the address. That's another diff. So let's take care of those. Now let's start with this top one here. So perhaps we can say, well, this diff will contain an h1 with that title. And then the next one is going to be, well, this is kind of like a three column setup. So we can set it up as a three column, we can set it up in any way we want. You know what, let's, let's keep it simple. I'll do another div. And then inside of this, I'll do three divs. So we'll have something like strong 153 posts, so strong 153 posts. What's the second 120 3k followers? Okay, do that now. Strong 23k followers. Okay, what's next? 212 following 212. Strong. Here we go. 212. Following. But of course, this is not quite gonna look the right way. Yeah, you see they're stacked on top of each other. No worries. It also looks like this is obviously going to need the same padding at the top. So let's just take care of that. Now. We'll say right here, padding top of five, that'll match that up. And then this div needs to have a display of flex. And that will bump everything from on top of each other, to next to each other. So there we are. So clearly, now we do need a little bit of padding, because as you can tell here, they're right up on top of each other. So let's add that right now. Let's say grab all these. Let's add a class of maybe padding right three Let's try three, maybe four, maybe five. There we go. That's pretty close. Right? Now we're Of course not seeing strong, right? We are not seeing bold here. Now let's see why that is. Let's go into our app dot SCSS. file. Yep, there it is. So we're pulling in this font right here, however, you see that we're only pulling in one weight, we actually need to bring in at least two weights. So how do we bring in fonts, obviously, as you see here, level is using the Google API fonts. So how do we get those fonts? Let's go back to Chrome. And let's go to fonts that Google com. So there we go. Now up Open Sans is a pretty common one. And this is actually the one that I do want to use. So how do we pull in this font? Well, the first thing we need to do is we need to click this button up here that says, select this font. And then if we click on this tab right here, and click on Customize, we see that we have regular, but we're gonna need a bold, so let's grab a bold as well. And then click back on embedded. And now if you click right here, where it says add import, now you see here, the same exact style of coding that you see back in our file, I'm gonna actually paste this down here, just so that you see that is exactly the same. So we are importing this Open Sans, and we're importing a weight of 400 and a weight of 700. Obviously, notice that on this other font, we were not importing anything at all. So let's keep it like that. But we still need to reference this Open Sans font right now, it just wouldn't work. So to do that, we need to jump into this variables. So to find variables, let's go into resources, SAS underscore variables. And now here, you do see that that font is being referenced right here. That's reference Open Sans. Now, is this going to work right away? No, is this is not going to work. Remember, we need to run that NPM command one more time, every time we make changes to our front end, we need to rerun that file. So let's go back here. Let's go back in here, and let's run NPM, run Dev, this will recompile all the front end for us. Hopefully, we'll see a change in that font. Alright, so that's done. Let's go back to Chrome, click back in our project tab, hit refresh. And sure enough, you see that now we do have bold, and we do have everything that we were expecting. And of course, we did change the font. Now since we are already editing that file, let's take care of one last thing. Now, I don't know if it's noticeable in the video. But this has kind of like a blueish background. And this should really be white. So let's change that. Now. Let's go back to PHP storm. And you see right here we have this body background. And again, like I said, it's like a bluish color. Let's change this to just plain all white. That's three F's or you could do the full method, which is actually six apps. And that just means white. So again, we made a change to one of our sass files. So we need to recompile our code. So let's do NPM run Dev. And then let's check out the difference. There we go. Let's go back to Chrome. Hit refresh. And there we go. So now we have a white background. And that's more like how Instagram actually is. Alright, let's keep going. So the next line is this free code camp.org link. So let's go to PHP storm. Let's close this up, close that up. Alright, so let's make a new div for that. And let's just paste it in. And go back to here. And let's grab this little bit of text. Now, I can already tell there's a quite a bit of padding right here. So we could probably just apply that just now. So class, let's do a padding top of four. And let's grab in our other texts. There it is. Let's see how we're doing. Refresh. Okay, not too bad. So that it looks like this is a, a bolder font. So let's do that. Now. Let's say font weight, bold, font weight, bold. There we go. And last but not least, we do have a link. So let's copy that link. And let's write that here at the end. So add a new div. And then we'll have an anchor tag, which will probably go to that link. Not to concern for that for now. I'll just put in a hash for now. And there we go. Now this is probably going to be blue. Yeah, there we go. You see this is blue, because that's just how bootstrap works. But we do know that our link needs to be black, or maybe like a dark blue, but don't worry about the front end too much for now. That's perfectly fine. So then we have our posts. So let's just grab the first three posts just so we have something to work with. So right after this row, let's add a new row, which is obviously going to be four posts. And this is probably going to be column of four. Because column four, if you remember, bootstrap has 12 grids all the way around. So if we need to put three items, then this is four plus four plus four. And of course, that's where we get the 12 from. So let's do that. Now let's add an image, what's the source? Well, let's grab the image right from Instagram. So to do that, it is a little tricky. But if you right click on it, and you hit inspect, and then you can browse around here a little bit, right until you find the image out is a little tricky, they don't make it very easy to do. So there it is. So there's the image, we'll grab the link, we'll put that one there. So let's copy that two more times. And let's see what we have obviously going to be the same image. And we run into a bit of an issue. And of course, we do have no resizing. So these images are quite larger than we need. And we don't have enough space in between here. So let's fix both of those together. Now, each of these images need to have a class of W 100. And this is all bootstrap stuff. But WP dash 100. Refresh, there we go. And then let's add a little bit of padding to the top. So we'll say padding top of four, maybe PT dash four, there we go, we got a little bit of breathing room looks like they have quite a bit, but they do have this post here, let's add a little bit more, just to have a little more spacing. See what that looks like. There we go much better. So give me just a second to fetch these other two images. And I'll be right back. And there we go. Alright, so we do have our images here. But of course, this is just the front end, we all we have literally done is just copied this design over. But now we can get to working. So what's the first thing that I want to tackle? Well, we do have our user, right, so let's just say that Free Code Camp is this user's account. So Free Code Camp, of course, is a username. But if you remember, let me log out. If we remember here in the register, there is no username, we have a name, we have an email, and we have a password. So we need to add a new column here so that when our user registers, they can tell us what they want their username to be. So let's take a look at how to do that. Now. Let's jump back to PHP storm. Let me close all this. Let's check out what actually got added when we ran the make off command. So if we look in here, inside our views directory, we have the auth directory. Now the off directory does contain a registered that blade that php file. And inside of here, we scan through it, let me get rid of this sidebar, we can see a little bit better, we do have this name. And it is a little bit more difficult to see. Because Laravel is actually using one of the language helpers. But ignore that for now. So name, email address, here, we keep going, we have password, and Confirm Password. So that, of course is these four right here. So let's just duplicate email address and see what we get. Let's come back up here. And let's select right here. Now you see how this is a form group of row. And that starts here and ends here. Let's paste that again. Hit refresh, there we go. So we need this to change to username. So label four, let's go ahead and change all the instances of email. And let's say user name. So I am using PHP storm. If you select something and do Command D, it will select all occurrences of that. And you just keep clicking that until you get to all of them. All right, so what do we need to change this to? Let's change this to username, so that way it actually says username, there we go. So we have username, and then we have this field here. So ignore a little bit of this for now. But we are able to get errors. What do we mean by errors? Well, the user hits register, and of course, it is doing the HTML validation. Let's get rid of that just for a second, just to show you what it actually does. If you look right here, through this input, you're going to find this required attribute. So let me actually get rid of all of them. So that we let Laravel do the validation for us. Let me hit refresh. There we go. So if we hit register, we do a post back to the server, and the server validates the data, and then it comes right back to us. That all happens very quickly. But if you take a look at right here, keep looking right here. I'm gonna hit register. And so you see that we do actually do a post back to the server with the data, the server validates that data and then returns back but we see that name field required email fields required, and the password field is required. Of course, our username is required. So that's clearly not working just yet, all we've done is added the markup for it. So let's go back to PHP storm. And let's take a look at another file. Now we briefly briefly talked about a controller as being a way of us having actual data, right, I told you that views should never hold the actual PHP logic, that would be the job for a controller. But we haven't really talked about controllers. So if we look at our files, we do have this app directory, we haven't really explored much of it. If we open that up, and we go into the HTTP, we do have this directory called controllers. And so controllers are basically where all of the logic is stored. So if you need to fetch some data, that's for the controllers for if you need to manipulate this data, and change it from ones to zeros, or whatever it is, you need to do to this data, that is the job of the controller. And it's not the job of the view, the job of the view, is to simply put things in the right location. But that's it, it should not be doing calculations, it should not be doing queries, none of that that is all jobs for the controller. So let's open up this controllers directory. And we have this off. Again, this was another directory that got added when we ran that make off. That's how powerful this command and it really does go in through your application and changes a bunch of stuff for you to get it ready to have users. So I'm glad we're not having to do this. Because it is a lot of work. There's a lot of little edge cases and things like that. It's open up off. And now let's go to the register controller. So as I said before, if the controller is what holds the logic for registering the user, then clearly the register controller is the one in charge of registering our users. Okay, that's fair enough. I think that was pretty self explanatory. Let's scroll down some. Now there's some stuff through here. We'll get back to all of this. But we do see this validator. Clearly, this validator is what we're using to validate our data. So all right, well, we have this email, we have this name, let's add a new entry to this array of username. And let's just say, Well, some of these are pretty self explanatory. But each of these strings is some sort of validation that needs to pass. So required, of course, means that it is required. If we have email, for example, that means it needs to be a valid email max of 255. Clearly, that just means that the string length needs to be less than 255 characters. And then there's this uniques users. Now, we're not going to touch up on this just yet. But just know that Lenovo is able to validate that that email address in the case of this is unique in our database, meaning that you cannot re register with the same email. So that's pretty cool. Let's check this out. Let's see that in action. I'm just, I'm not even going to put a name, I'm just going to do test at test Comm. Obviously, that is our email, I'm gonna hit register. And it says this emails already been taken. That's pretty cool. So if we get rid of this, right, it's safe. Let me go ahead and register again. Now you see, that passes validation. But we know that this would run into trouble because we cannot have two users that have the same email address. So that's pretty cool. That level is able to do that. And it looks like it's pretty simple. all it's doing is it needs to be a unique on the user's table. Fair enough. As a matter of fact, this username also needs to be unique, we cannot have two users with the same username. So we'll keep that will keep the Max 255. Obviously, email, let's get rid of because it is not an email. So our username needs to be required, meaning it needs to be present, it needs to be there. It needs to be a string, meaning it should not be some floating point or anything like that. And it can only have up to 255 characters, and it needs to be unique in our users table. So all of that with this single line of code, we're going to be able to validate all of that for us. So let's go ahead and hit register now. And sure enough, we do see that the user name field is now required. So that's pretty cool. We are able to do that. However, we're not quite done just yet. We've taken care of the validation. But to be honest, you remember migrations, we talked about them already, migrations, again, describe your database. So if we are adding a username to our users table, then of course, we need to make a modification to our migration. Because our migrations need to know that we are now going to know about a username for each of our users. So let's go back to PHP storm and talk a little bit more about these migrations. So let's go into my close app just so it's easier to see. And we do have this database directory. And inside of there, we do have migrations. Now currently, there's only two of them, the Create users table and the Create password resets table. I'm interested in the users table. So if we look in here, we obviously see what looks like a database instruction. So we're making a schema, if you're not familiar with the word schema, it just means it describes the structure of the database. So we're telling schema, go ahead and create a table for us with the name of users. And then this is the blueprint for the blueprint is going to be some sort of big increment ID, meaning it's just going to be an auto incremental ID. And then we're going to have a string for name, a string for email. And this one needs to be unique. And then we're going to have a timestamp for email verified on, which is nullable nullable. Meaning it could be no, it could be it's optional, it is not required. That's what that means. And then we're gonna have a string for password. And then a remember token and timestamps, a lot of stuff here that you don't really need to understand right away. But we do know this, we need to add a new username. And it doesn't need to be unique, meaning it is required. But it needs to be unique. Again, the username cannot be repeated, two users cannot have the same username. So we'll keep that in the unique constraint. Now, this is adding a unique constraint at the database level. This is different from when we registered it here. Because this is at the PHP level, this we're just checking. But if for some odd reason, someone was to post directly into our server and try to basically use the backdoor, which we of course want to be protected from still, our database is going to protect us and make sure that no one makes a user with a username that already exists, because that will cause all sorts of trouble for application. So that is cool that we are able to do that right here. So that's it, we've added that. But there is one more step back here in the register controller, if we scroll down a little bit further, this is where our user actually gets created. So this is matching up to this data up here. So once we pass validation, then we get to the step where we actually create a new user after it is a valid registration. And again, a valid registration is everything that passes the validator. So once we're in this step, we know that all the validation data is correct, everything is good to go, we can create this user. So it is safe to assume that at this stage in the Create method, everything is good. We don't have to do any further checking. So we can blindly kind of say, well, we have an email. But we also know that we have a username, I'll replace both of those together. So username. So now we're going to have a name, an email, a username and a password. Sounds good. Let's hit save. And let's see what happens is actually try to register a new user. So new user, and then test to at test. COMM username is going to be test username, password, we'll just keep that one through 10. There we go. Hit register, we're gonna hit an error. But I do want to show you how that works. So we hit register, right, but it seems like it worked. But it didn't quite work. And so the easiest way to show you this will actually be to show you how to interact with your application through the background. And that is using Tinker, we're going to be using Tinker throughout this whole entire course. And it is very powerful in development. So let's run php artisan. And let me show you what that command is. Let's scroll all the way up to the beginning. And we do have this Tinker command. So let's run php artisan Tinker. And now we have this prompt. So at this point, this is our application, we've essentially logged into our application and we are emulating PHP. So if we said user, uppercase, U, colon, colon, all that's basically a command. Now we see that we have two users. Of course, we have our test at test, comm user. And we have test two, which of course is the one that we created. But there is absolutely no reference to the username. So we must have done a couple of things wrong. Well, first and foremost, let me exit out of Tinker. First and foremost, we need to run php artisan migrate. Remember, whenever you create a new migration or you make changes to your database, basically you need to remake your database. So we can run migrate fresh, and that will erase everything and create everything again. So you see it drops all the tables, and then it migrates our database one more time. Great. There is one more step. Let's go back to PHP storm and let's go up here to app. And then there's this user that PHP class. This is a model. A model, as the name suggests, models a row in our database, meaning that one of these user classes just represent one row inside of our database. So if we look through here, we see that the attributes that are mass assignable are name, email and password, meaning that nothing else will be able to be filled. Now the reason for this is just an extra layer of protection that level is giving us so that a malicious user does not add anything to our database that it's not supposed to be there. So of course, as we've done before, we need to replicate this and we need to add a new one for username. All right, I think now, we are ready. If I hit refresh, right now, obviously, it bums me out, because when I ran the php artisan migrate fresh, it actually erased the entire database, remember, dropped all the tables? Well, we lost all the data. So let's register a new user. So now I can go back to using test user again, because that doesn't exist in our database again. And username will say test username, password, password, register. Alright, so this time, it looked like it worked, but didn't really work. Alright, let's go back to tinker. php, artisan Tinker. And let's run that command again, user, colon colon all, give me all of my users. There we go. So now we've successfully added that username, test username, just for reference. Here it is the command right here that we ran it the first time, notice how there's only name, email, email, verified that. But there is no username. Now we have name, email, and username, which is actually what we added. So now we are successfully registering a user with a username. So let's use that username. Now, in our view, let's jump back to PHP store. And let's check out how we can change something. Let me show you first. Let's go back here to Chrome. Now up here, you see that we have this test user. But in the actual Instagram page, what actually shows here is not the user's name, but it's actually the username. So let's find that and change that. So back to PHP storm one more time. And what are we looking for? Well, remember that is inside our navigation. And our navigation is inside that app that blade that php file. So let's check this out. Let's close this up so we can see better. And we have views, and then layouts. And then app dot blade dot php. This is where that file lives. And we're going to talk a little bit more about views and why this is inside a layout file and how layout files work and all of that in a little bit. But just bear with me here a little bit longer. Alright, so let's scan through this file now. And let's try to find that username. So there it is. So this section here represents that right side over there. And if you see here, we're fetching the authenticated users, and then grabbing their name. What if we just grabbed their user name instead? Let's check this out. And now we get test username. So that's pretty cool. Now how else can we use that username? Well, we know for a fact the username is actually this right here. So let's substitute this in our view, because Free Code Camp is just something we hard coded in. But that is actually the username, let's go to our home view. And there's the text that we're trying to replace. Obviously, we're trying to replace this, but we need our data. And if you remember, I said that the data needs to come from the controller. So right now we don't really have a controller have we we haven't really worked with one yet. we've kind of been just using what Laravel gave us. But let me show you a new file. If we go to our routes, routes file, and then we go into web dot php, this routes file is where all of your routes are registered. So in our case, obviously, we are going to the slash home in our browser, here we see that represented as slash home. And that is just calling a home controller. And this notation here you may not be familiar with this is a Laravel specific indication that we are calling the index method inside the home controller. Let's fetch that now. Let's go to the home controller and look for the index method. And there it is. And so we see that we are returning a view called home what is home represent? Well, again, let's dive back into resources views. And of course we are talking about this home that blade that php file right here. So home represents this right here. Now notice that home is home and not home that blade that PHP Laravel is smart enough to know that of course, it's inside your views directory and it is called home dot blade dot PHP is the actual name for the file, but home All we have to put in. But this home controller, this is one of those controllers that got created with the make off command. And so it has this right here where it is requiring us to be authenticated. But to be honest with you, let's check this out is that the right functionality? Back in Instagram, we're actually not even signed in, check this out, you see, we have the login and signup buttons down here. So clearly, this should be viewable even if the user is not signed in. So what I want to do is I want to stop using this controller altogether. And I want to make our own controller. So how do we make a controller back in the terminal, let me exit out of Tinker. And what we're looking for is a make command, make commands will allow you to make all sorts of different things, obviously, we ran the make off. And that's the very first command that we ever did. But there is this MC controller. Now one thing about php artisan is that you can run php artisan, and then help and then followed by any command inside of here to see what sort of options you have, what sort of required parameters you have to pass in or anything like that. So we check this out, we have the description is it creates a new controller class, great, that's exactly what we want. And the usage is main controller, and then you can pass it in any number of options. And then if it's inside, a less than and greater than that means it's required. So the argument of name is required. Now that makes sense. If we're going to make a new file, then we need a name for that file. So PHP cannot guess that for us, we need to tell. Alright, great. So let's go ahead and try that now. php artisan. Let me clear the screen. So php artisan, make controller. And what is the controller name? Well, this is a very important convention to learn. So right now, obviously, this is called home controller. But is that are we showing home? Is this home? Maybe originally it was. But what could we call this? Well, this is a profile, is it not? This is a user's profile. This is what it's going to be the test username profile in a little bit. So why don't we call that the profiles controller? Let's see profiles controller. Okay, so let's check that out. Let's go back to PHP store. And now we can go into app HTTP controllers. And then we have our new profiles controller. And then what I want to do is just to keep everything simple. Let's jump back to the home controller. And obviously, we have this right here, this index is kind of what we've been using. So let me just paste that into here. And so how do we direct level to this controller instead? Well, it's as simple as going back to our routes, web dot php file. And instead of home controller, let's use our profiles controller. So profiles controller at index. Remember, index is simply just the name of the method. Let me close that. And back to my profiles controller, it's matched to right here. So web index, and then over here, index, same thing. Alright, let's check that out on the browser, make sure we didn't break anything, we should see exactly the same. Great. So so far, so good. Now, let's talk a little bit more about this profile. This profile obviously needs some data, right. And we need, for example, the user's name. And there are several ways that we can grab our authenticated user. But it doesn't mean that it is the actual user, this would kind of be considered a detail view, right when we're talking about restful actions. And index action means that we are showing all of the resources. And this is not showing all of the profiles, this is showing a single profile. And what I want to show you is a little bit of the documentation of Laravel. So let's jump into Laravel. And let's just do a quick Google search for restful controllers. And let's see what we get this very first result here restful resource controllers, this is what I'm interested in. Laravel follows the convention of a restful controller. And if you've never seen this concept before, it is basically a predetermined number of verbs that you can use. In our case, obviously, it's gonna be seven. And each of these actions will be matched to a particular URL, verb, an action, and it even has a route name. Now, it is imperative that you follow this convention, because it's going to facilitate your development tremendously. It's going to make your controllers lighter, it's going to make your application way easier to update and all in all, it's going to make your code base that much cleaner. So it is an important concept and I do definitely want to stress how important it is to start to use these actions. So let's check this out. We have this show action. And now I'm going to give you a little bit of a heads up this is kind of the one that we want because we are getting a specific person For one user, we're grabbing the one user's profile, not a ton of them, if you will grabbing all of them, then obviously, that would be an index, think of an index as the Index page of a book, it's got a bunch of references in it. But that is not what we're showing what we're showing here is a single profile. So with that being said, this is the convention, you'll have photo, and then you'll have these curly brackets make it a little bit bigger. So it's easier to see, we do have this curly bracket notation, a curly bracket notation in routes, just simply means that it's a variable, it's going to change. And you've probably seen this before, what we kind of want to see is something like profile slash, and maybe ID of one, we want our profile to show up for user with ID of one. Now, Instagram does follow a little bit of a different naming convention, you see that they actually have the username, and we're going to do that as well. But I want to show you this way first, so that we're clear on what the actual procedure should be. So let's go back to PHP storm. And let's check out the web routes. So let's make let's make some changes here, let's say slash profile, slash, and then we know we're gonna have some sort of variable, and that is determined by the curly brackets. So in here, what are we looking for? When we're looking for a user? Are we not? Our user is the one that is going to have the username in it. So what we need is a profile for a user. Okay, so we have a user, we have our profiles controller, and then let's call this, let's find out, let's go back here. Let's call this resource name dot show. So let's say profile dot show. Okay, so far, so good. So now how do we get access to this variable right here? Well, as it turns out, is quite simple. It's going to be given to you through an argument in this function. So we'll just say user, and for now, let's die. And dump DD is a nice function you can use for development, it will echo out whatever user is, and it will stop all operation. Is it safe? And let's go back here. And let's try to visit that profile slash one. And there we go. We do get one back one, meaning what we're passing in. So we passed in blah, yep, we get that anything you pass in here will get passed into that right there? Okay, well, that's pretty cool. However, that's not what we need. We we need the actual user, how do we get the actual user, I'm gonna show you the long form of that. So we spoke about having a model for our user. So if we go into app, we do have this user that PHP, and remember that I told you that this model represents a single row in our database. So that represents a single user inside of our database. Okay. So if we go back here, how do we get the actual user? Well, you could say, user, colon colon, find? So what are we finding, we're finding the user with that username. Remember that this is going to give us the ID of the user. Now, this class is not in the same namespace as this controller. So you have a couple of different options. You can either say, app user, and then it can find it. Or if you have something like PHP storm, you can actually import the class. And what that will do is add this line up here. So use App user. And so when we reference user, what we are really referencing is app user as we are up there. Let's check out what that means. Let's do a die and dump on Matt. And let's just see what we get. Refresh. So we get no, because obviously, 123123 is not a real user. Let's go one. And try that. There we go. We're actually getting our user. So you see here, we have a user class. And let's check out the username, test username. Great. So we are able to fetch our user. So we're one step closer to what we need. We're not quite there yet. Let's save this to a variable. And then let's pass it to the view. So that's the next part. How do we pass data into the view? Well, as it turns out, as a second argument, you can pass in an array. So let's say user is going to be equal to our user. user is what the variable name is going to be inside of our home. So here, you may be familiar with the Echo, the shorthand for Echo, in PHP, as less than question mark. And then you could put user, for example, something like that. Now, in Laravel, there is a nicer way of doing that. So to echo out anything in your views, you're going to do two curly, we'll call the mustache syntax. So two curly brackets. And inside of there, we can say user, and then what do we need? We actually need the username. Okay, let's see if that'll work. Let's hit save and Refresh. And there we are, we are passing data into our view. Well, that's fantastic. So what else do we need to do? Well, there is all this other data here. But for that, we're actually going to need another model. And what I want to do is I want to create a profile model, I want to have a table specifically for profile information, because you have your users but then you have their profile that's a little bit different than a user. So let's tackle that. Now let's make a new model from scratch and write a migration and everything like that. So let me jump into the terminal. And let's see, we can run php artisan. And let's check out what we have available for us. So if we look through this, of course, we have a nother make commands. And the main command we are looking for is make a model. Remember, one more time a model represents a table in our database. And one object of a model represents an actual row in our database. So what do we want to represent in our database? Well, we want to represent a profile, right? So we have a user, and a user is going to have a profile, right? This is very common, Instagram, social network kind of thing. So how do we represent that? Well, let's see what we need for this command, php artisan help make model. Let's check this out. So this creates a new eloquent model class. eloquent, the word This is kind of the first time we've seen it. But eloquent is what level calls the database layer of the framework, just a fancy word for basically, the implementation that Lenovo users behind the scenes to fetch queries, and everything like that is actually quite powerful. Because you can have eloquent models that are actually database agnostic. And what that means is that you can use SQL lite, you can use MySQL, you can use Postgres, you can use any number of different databases, but you're writing the exact same code. So if you learn how to write eloquent queries, then you can write for any of the other platforms. In our case, obviously, our example is running right now in SQL Lite. But in a real production server, you're probably going to use MySQL, Maria dB, some sort of implementation of MySQL. So that makes it powerful, because we were writing the code in SQL lite, but we can deploy it to any other database that we have in our production server. So that's great. Now eloquent, again, that's just the word for what it actually does. So make model, like the make controller requires a name. But Furthermore, we have this dash m that we can run, that will also create a new migration. So if we are creating a new model, then it makes sense that we need to describe something new in our database, meaning we need a new migration, if you're going to represent something in your database, then you need to describe it inside a migration file. So this will do all of that for us in a single command, it will actually create two files for us instead of one. So let's run PHP, artisan make a model. And what is the name of the model, we're creating a profile. And let's run the dash m flag, set, Enter. And so we see that our model was created. And it also created a migration of create profiles table to its name that for us, it knows what to do, it's set up and ready to go. That's what makes artisan so great. Alright, let's jump back to PHP storm. And let's check out these new files. In app directory. Of course, now we have this other model up until this point, user was the only model that we had. But now we have a profile. But this class is empty, it doesn't quite do anything, it actually extends model. So it does have a lot of functionality, but it's empty right now. Let's also check out this migration that we created. Let's go into databases, migrations, and then create profiles table. So in here, we have something very similar to what we saw, when we added something to our users table. That was the username. So we need to make a profile. So what is a profile going to hold? Let's go back to Chrome. And it looks like we need number of posts. Well, that's going to come from a different place. Same as followers, same as Following this, we're not going to count that in our profile. Our profile right now is going to consist of this right here, which I will just call title. And then we have this text right here, which is basically a description. And then we're going to have a URL. Okay, so let's jump back to PHP storm and try to make that work. So let's describe our table is going to need a string for a title. Now a string is fairly short, right? So a string will be something like a title or a URL. This right here is more of a paragraph. So you will actually use text instead. So we'll say text description, and then we need a table for that link. Right? So table string, and let's just call it URL. So out of these three things here, all three of them Actually nullable, because when the user first creates their account, they're not going to have a title description URL, that's kind of the complete your profile sequence that most registrations take place. So all three of them, we're going to make them nullable. That way, the user is not required to have them at all times. But this table right now needs to connect to our user, because a user has a profile and a profile belongs to a user, does it not? Right? It's a one to one relationship. Of course, we're talking about relational databases. So your different tables are going to have some sort of relationship with each other. So how do we connect that? Well, at the database level, we need to have a table and we need to have a column with unsigned, big integer. And what do we call this? Well, we are associating this to the user model, right? So the convention is user underscore ID. So that's all we need, we just need to store a reference to the ID of the user. That way, we know that this profile belongs to that specific user at that ID. So just for good measure, let's add an index. This is just for better searchability and quicker queries. So we're just going to add an index on user ID. And typically, you're going to want to add an index for any foreign key that you have in your table. That's what this is called. This is called a foreign key, meaning it represents the key in a foreign table, meaning not yourself, but the table, in this case, the user table. So we have this setup. So what will be the next step? Well, you may have guessed that we have to migrate our database where we want to tell them about, well go ahead and implement this new description that we just did. So we do have the up method, and that's what's going to run. But do keep in mind, there is the down method, migrations can run forwards and backwards. So when you run backwards, meaning you're reversing what you did, that's when you run the down method. Now, Larry has been nice enough to create the down method for us. And all it does is it deletes that profiles table, because if we create a profile stable in the up, then of course, we delete the same profiles table in the doubt, it just makes sense. Alright, so with all that being said, let's go ahead and migrate our database. So we can add this profiles table to our database. So PHP, artisan, migrate. And so we see that it migrated, and it created the profiles table. So we've taken care of the database level connection that we need to a user by doing this line right here. But we still need to let Laravel know how to handle this relationship properly. Now, we use a couple of keywords in the previous explanation, where we talked about how a user has one profile, and a profile belongs to a user. Now, that is just plain English. And Laravel has done a great way of transitioning that into actual code. So we're going to write it just like that. So let me show you how to do that. I'm going to close that. And we're back in the profile model. So in the profile model, let's add a public function. And we're going to call it user and the user. All this needs to return is this belongs to, and what does it belong to? Well, it belongs to a user, colon colon, class. So that's it, a level will take care of creating that relationship, and fetching a user underscore ID. Now notice, we followed a very particular naming convention, it is possible to override the default. But in our profiles table, let's check that out one more time. So create profiles table, we have this user underscore ID, that matches to our user model right here, user singular. And then in our profiles, we're saying this belongs to a user class. And this method is also called user, notice how user and user are the same name. So if you follow that convention, now, we're going to keep doing this a couple more times. So it's going to become a little bit more clear how it actually works. But if you follow that convention, then you don't have to do any weird overrides, where you actually have to let level know what it is that you meant to do. Now, sometimes it doesn't quite make sense to call it exactly what it is on the database. And in that case, of course, you can go ahead and do that. So we actually visited this belongs to method, you see that, yes, this is the related method. But then, as a second, and third parameter, you can pass in the foreign key and the owner came meaning you can tell it, hey, learn about, yes, this belongs to say a user. But we're actually calling the foreign key. I don't know, client underscore ID, as opposed to user underscore ID. And that would work level will be able to do that for you. But in our case, we followed all the conventions, so we don't have to do that. So back to the profile model. So we have this relationship here for the user. But now we need to write the inverse. Now. You don't have to Write the inverse for it to work, right? If we just left it like this, then a profile could always fetch a user, that's no problem. But we want to be able to do it in both directions, we want to have a profile, and we can fetch the user. And we want to have a user. And we want to be able to fetch their profile. So let's do the relationship on both sides. So on the user end, scroll to the bottom, let's go ahead and add another public function. And let's call this profile. And again, a profile belongs to a user and a user has one profile. So return this has one profile class. Now notice something here, notice how we did not have to do say app profile, we didn't have to do that. Because if we actually go back up here, this is in the app namespace. And profile is also in the app namespace. So there's no necessity to actually have the full namespace or use one of these use import syntax is at the top like we did previously, because it actually in the same namespace. So when we say user, in the profile, we're actually going to be in the app user, because that's the namespace of this file. That's just basic stuff in PHP, nothing to do with Laravel specific. Alright, so we got these hooked up at the database level, we got them hooked up at the level level. So now it's time for us to manually add a profile. And then we can go ahead and connect them together manually, just for now, just so I could show you how it actually works. So what we'll do is let's jump into Tinker. php, artisan Tinker. Now, I haven't really shown you how to do this, but let's go ahead and add a profile through the command line. And this is going to be a cool learning experience. So we can say remember, Tinker is like interacting with your application, one PHP line at a time. So we can say something like profile. profile equals, and then we can say, app profile, actually, we can say, equals new app profile, there we go. So now we're gonna have a nice app profile class. So then we can say, all right, profile, set your title, equal to cool title. Okay, then also profile, set your description, to description. And that's good enough for now, we remember we do have that URL. But that's not necessary. Now, if we tried to save this, right now, of course, it would fail, because the user ID is not knowable. So it does need a user ID. So let's go ahead and say, profile, your user underscore ID is equal to one, right? That's our actual user, if you remember back here, this idea of one, so that's what we're gonna assign that profile to. And then we have to call his profile safe. And that will persist that into our database. Cool. So now, we have this profile, we can actually call user. And there it is. So notice how we fetch the user through the profile. We didn't fetch the user by itself. But we actually were able to use that relationship and call the user. And so what we have here is an app user, not a profile. So we have our profile. There it is. And then we can say profile. Give me your user. There we go. So now let's actually do the inverse. Let me clear this up. And let's say, let's grab the user and say, app user, find one, exactly the same thing we did in our controller. And now let's say user, give me your profile. And there it is, we grabbed the profile. And we have cool title, we have description. And we said the URL wasn't all because we didn't pass anything in. So that's pretty cool. So we are able to fetch the relationships forwards and backwards. All right, so armed with that knowledge, let's write some code. Now. Let's go back to PHP storm. And let's work on this view a little bit. So let's go to our home, that blade that PHP. And now we have a little bit more to put into this, right. So we now have these three lines that we can make dynamic, obviously up until now, they've just been hard coded in. So let's make them dynamic. So we have, we have our mustache syntax. And we can say user. So after we have our user, you got to remember we have our user, what do we need, we need their profile. So now we have their profile. So now we need the title. So remember, this will return our user, this will return our profile. And then this will just fetch this specific column in the database. So title in this case. Alright, let me go ahead and change this one as well. And we'll say one more time. So we have our user, and then I want you to go into their profile and I want you to give me their description. Okay, and then finally, the URL So let's go into our user, grab their profile and give me their URL. Now we know that this is nullable. So what do you expect to happen? Well, Laravel is smart enough to know that if something is nullable, it's just going to be an empty string. So we're not gonna see anything for the URL column. And that's okay, I'll show you how to actually set a nice default for that. So hit save. Let's go back to Chrome. And let's hit refresh. And there we go. So we are now fetching cool title and description out of our database. Now URL, it is there, there is a new line, but there's nothing there. So let's actually write a nice default that we can have for that. So the way that we can do that is right after this URL, will say, give me the URL from their profile. Or, and the way we say or is with a double question mark, or just say, maybe not available. Okay, so let's go back here, hit refresh. And now we see it's not available. Now, this isn't a great example of how to use this because this is still a link. So if we clicked on this, and it was na, it just would not work. So probably, that's not a great example. So I will actually erase that. I'm not crazy about that. So we'll leave it like that for now. But let me show you now how we can maybe give that user a URL so we can actually show it. So let's go back to tinker. Let's see what we have. Well, we have our user, right, yep, we have our user. So let's say user in your profile, I want you to set your URL equal to free code camp.org. And then, how do we save this? Right? So if we said user safe? That wouldn't work? Would it because what we're actually saving is the user. And I'll prove that right now. I'm going to go back, and I hit refresh. And you see, yeah, we don't, we're not getting that URL. That's because we are not saving the user. But we're saving the relationship, we're actually saving the profile. Wouldn't it be nice if we could just recursively save everything and just say almost like a save all that you're used to maybe in a code editor or something like that, just save all go ahead and, and do that. And there is actually a way the method is actually push. So let's say user, go ahead and push. And what push is referring to is push my changes into the database, whatever it is, that is right now, dirty, basically, it is different than what we actually have in my database, go ahead and push those changes up. And if we do that, let's go back and see the difference. Now, notice out here, there's nothing underneath, I hit refresh. And there it is. Now we get that. So that's a very cool, nifty trick. Imagine you have multiple relationships on a model, but the user is kind of the god model, right? It's holding everything by itself, you make a bunch of changes to different tables through the relationship, and then you say user push, that's it, you don't have to worry about going into each individual one, and saving your changes to the database. So that is a fantastic method, you're going to use that all the time, we're going to keep using it throughout this course. And it's going to become a little bit more clear when to use it and when it's appropriate. Alright, so we are properly doing this. Now one thing I want to take care of is right now, watch this. And we say profile to everything blows up, right? What happened? Well, in the simple terms is there is no user by the profile, too. And everything blows up. And that's not quite what we want, right, we really just want to have a maybe a resource not found type of 404 error, not this blowing up thing in our application. So let's go back. And let's see how we can actually handle that x PHP storm. And let's go into our controller, that's profile controller. And there we are. So right now we're saying user find user. So we're assuming that this right here is always going to be a valid user. Now we know users are crazy, they're always going to try to do things to break our applications, users can never be trusted. So with that in mind, we need to be a little bit more defensive about it. So let's change this find. And let's do another call, and it's called find or fail. So what this will do is, instead of failing on gracefully, the way that it just did, it will actually return the proper response for the user. So let's go ahead and hit save and go back here. Hit refresh. And sure enough, there it is. So now we get a four, four, not found much different error, much better. It is a proper response, as opposed to returning maybe a 500 indicating that something went wrong on the server level. That's not correct, right. We know that two doesn't exist. So it is not a 500. It is actually a 404. So let's go back to one. And there we go. Boom. So we have our users and then if they decided to say blah, then of course they just get a 404 not found that is the proper response for that. Great. We are making great, great product. So up next, let's talk a little bit more about this relationship. So we created this profile, right. But now we have this section here, right? So we have these posts. So I post is going to be yet another model. So let's go through the sequence. Maybe this time a little bit quicker now that we know kind of what we're doing grading the migration, creating the relationships, and all of that, let's go a little bit quicker through this. And the next relationship that we're going to tackle is going to be a one to many, because of course, there is one user, but they're going to have many posts. So this relationship is a little bit different than a profile to a user, because there's always going to be one user associated to one profile, that profile cannot belong to more than one person. And that user cannot have more than one profile. However, now we're going to have a user and a post. And a post belongs to a user. But a user can have many posts. Of course, that makes total sense. So let's go ahead and get right to it. I mean, exit out of Tinker, clear this up. And let's say PHP, artisan make, model. And what are we making? Well, we're making a post model. And let's go ahead and get a migration for that. Alright, so now that we have our model, back to PHP storm, let's start with our migration. So create post migration. So what do we need for a post? Well, first and foremost, a post, of course, needs to belong to a user. So we need a reference of user ID. So unsigned, big integer, user, underscore ID. And of course, as always, let's go ahead and add a nice index for that. So table, index, user underscore ID. Now Laravel, does allow you to do very cool stuff at the database level through this, for example, if tomorrow the users account is deleted, well, there is no reason for us to have the posts or the profile, right? That should kind of go with the user. So if we deleted the user, then we should probably delete any posts that they've had. And we should probably also delete their profile. So at the database level, we are able to handle that, that's a little bit more advanced of a topic because it involves cascading. But just keep that in mind. So you could theoretically right from here, delete this record of posts, if the user was deleted. So we'll have a user ID. And what else are we going to have? Well, this post, of course, for now, is going to have maybe a text of title. And it's going to have a text of description. And finally, this, of course, is going to have an image, right, that's the whole point of Instagram. So this will just call the image now this, you know what, let's keep it simple. Let's delete the description, we'll just call this caption. I think that's what Instagram called it. So we'll have a caption and an image just to keep it very simple. So we have our user ID, we have our caption, we have our image. So what's next? Well, we got to migrate our database again. So let's go back here and say PHP, artisan, migrate. And sure enough, we now have a post table. Great. Let's go back to PHP storm. And now let's hook these up at the Laravel level. So first and foremost, let's go into our user profile. And say a user, of course, can have many posts. So public function posts. Now notice here, it's plural, right? This was a profile singular name wasn't profiles, it was profile without an S. But this is plural, because when you have a has many relationship, then obviously, his posts, not post. That's the proper grammar. So return. This has many. And then we'll say post, AP class. Perfect. So post class. So this user has many posts, let's go ahead and write the inverse in the post model. So in our new post model, we'll say public function, user singular. And then we'll say return this belongs to belongs to a user, colon colon class. Great. So we are all set up at the Laravel level as well. Great. So of course, we could go through Tinker again, and go ahead and grab that. But I'm not going to worry about that. For now, I'm going to actually show you how to drive that out through a form. So first and foremost, what I do want to do is maybe create some sort of button, right, and we're going to need now obviously Instagram in the real Instagram, there is no real button to add a post because you actually cannot post through the web. So we're going to have to kind of make this up a little bit. But I think it'll be alright, we're going to create a button somewhere over here in the UI, just to add a new post. Alright, let's do that. Now. Let's go into home that blade and we have Here, just for now, let me go ahead and add it right here. Let me split this up into different lines, so it's easier to see. And let's just add a button, you know what this is to add a link, this is going to be easier a link. For now we don't know where it's going to go, we're gonna say add new post. And we go back here. And there it is. And we kind of want it to be kind of over here on the right. So let's do something. Let's give this div a class of flex. Now it's going to be inline. There we go. And now we need to push that all the way to the right. So we can say justify content between. There we go. So that pushes it all the way to the right. And now the only last thing we have is, well, that should kind of be down here, right, it should not be up there, that doesn't really make any sense. So we can align items to the bottom and align items baseline. There we go. So now the bottoms of them are actually aligned. And that makes more sense, whenever you have text that's supposed to be in a straight line, which should be lined up is not the top of the font, but the very bottom of the font. Right? That's what makes more sense to the eyes for the bottom to be lined up. So that would be appropriate. Alright, so add new posts. So when we click this button, where should we go? What should the URL actually look like? Let's see what Instagram actually does with this. Let's go back here. So let's just pick one of these right here. And it pops open in this kind of pop over. But if you click this little button right here, you can say Copy Link. And this will actually give you a link to the actual post. So we load that page instead. Now we kind of see the same thing, but there is no profile behind. So let's check out what they did. So they did slash p for post. And then they did some sort of unique ID on that post. So let's just go ahead and follow that slash p, I would normally probably just say posts, you can do post, you can do slash p either way. Since we're kind of creating a clone out of Instagram, let's go ahead and just follow exactly what they did. So slash p it is. So where are we going on this then, so we're going to go to slash p slash create. Now if we go back to our HTTP controller, the Create is a get route that you will have for the form, right, and this form will post to the resource itself. And that's going to hit the store method. We'll get through all that in just a second. But just keep in mind, this is where we're at right now for that. So it should be P slash create. That's what we're actually looking after. So let's head back to PHP storm. And let's start with the easiest thing, and the easiest thing would be for us to create this route. So web dot php, let's go ahead and add it right here. We'll say route get slash P. And what is that gonna go to? Well, it's gonna go to a new controller that doesn't exist yet. It's gonna be posts controller at back to Chrome, create, right, that's the action that we're going to take. So that's going to go to create, just go back here and say, at create. Now, we could give this route a name, but we're not using them right now. So we'll keep it like that for now. So now let's create that controller back to item. php, artisan, make a controller, posts, controller. And there we go. So back here, let's go into post controller. Now just a quick tip, you see me kind of switching files around and pulling this window up and typing up, get used to doing that find in your editor how to kind of jump from file to file very quickly. This whole going through the left here panel, and clicking through your stuff and HTTP and controllers, that is very, very slow. As a matter of fact, that even takes up a ton of real estate here in your screen. So we can actually get rid of that altogether and just focus on the code. Because this is a crash course. And there's a lot going on, I'm leaving it open, just that everybody has an idea of where we're at. But typically, I wouldn't even have that open. So just keep that in mind. So every code editor will have some sort of quick file jump command. So go ahead and find it for your particular one and use it from here on out. So again, we're looking for the post controller, and here we are. And if you remember, we're creating the form. So there it is. So what are we going to return? Well, for now, we need to return a new view that doesn't exist yet, either. And we'll say, well, let's put this in its own subdirectory posts, right, so let's go into our resources views. And right now we've been working with home that blade. As you can imagine if we had hundreds of views. This needs some organization, and it's going to be in the form of some sort of directories. So let's do that. Now. If we said views, let's go ahead and create a new directory. And this is going to hold all of the views for our posts. So posts, and inside of here, that's where we're going to put our view. So you can say post, you can either do slash or a period, up to you, it's the same thing. I like the period, I think it looks cleaner. But you can always use the slash, so post, period, or slash either one, create. So I name all of my views following the same convention as my controller. And I put them inside a directory, which is basically the first part of my controller name. This naming convention will help you find everything you need in your application. And it doesn't matter how large it gets, it always makes sense, you don't have to think about what you're going to name things, you're just going to automatically name it what it is. So if you have the posts controller, then all of the views for that are going to go inside a post directory. And for each method that you have, you're going to have a view with create now doesn't mean that we're only going to have one view, it just means that the main view is going to be called the same thing as the function. So if it's create, then it's create the post controller, all the views are inside posts, that's just a very easy convention to follow. Stick a look at this home, that blade that PHP, we haven't talked much about it. But this file is extending the layout file. And this is something that's very particular to blade. So you're going to create your views by stacking views inside of each other, a lot like the way that you would build layers in Photoshop or something like that, you're going to have your base bottom layer. And that's going to be your app layouts, right. So let's check that out. If we go in here, check out that file. This is the one that actually has all of the beginning stuff, the head, the scripts, the title, and the navigation. Now that makes sense. You don't want to be repeating this over and over and over. And then right now what we call home doesn't quite make sense, because what we actually call home is a profile. So we're going to refactor to that. But for now, just know that this is extending that. But we have this section here and this section, where How does level know what to do with that, if we go back here to app and scroll down a little bit, we'll see this yield keyword. So wherever you yield, and you can yield as many as you want, wherever you yield, that that's where that content is going to end up. So you can yield separate sections, sometimes I'll yield something in the head. For example, if I have a particular script that is only particular to one page, I can yield a script section, you can use the title, you can yield just about anything. And I'll show you how to do a little bit more of that in just a second. But for now, again, this home, that blade that PHP, this is not really following the same convention that I was talking about with this, right, because we have our profile controller. And our profiles controller has this index method. But there is no view called profiles dot index. Why don't we do that? Now, I think that'll be a good exercise. So let's go ahead and move this home. And let's actually create a directory first. And again, what is the directory going to be called? Well, it's going to be for the profiles controller, so profiles exactly like that. And then we're going to take this home that blade and let's move it into profiles. And let's go ahead and rename it once it's in there. So profiles is not home, that blade that PHP, but it is the index, right method name. So index dot blade dot php. Alright, so let's refactor. Rename is not home. It is index dot blade dot php, refactor, there we go. So now here is no longer home, but rather is profiles dot index, that's going to be our view for that particular resource. So let's go back here, and hit refresh. And if we did everything, right, of course, it keeps working, there is no visual difference for that one, that is just a convenience, refactor. Alright, so now that we have that, let's keep going with what we were actually doing, which is this post controller. So this create, let's go ahead and just copy for now, let's modify this one. So I'm going to make a duplicate copy of it. And it's not index. It's create that blade that PHP, and it's not going to be inside profiles, but it's going to be inside posts, hit OK. And now we've created a copy of that. I'll go ahead and just delete all of this, as we don't need it right now. All right, so we are good to go. So let's check out our files right here on the left. So inside posts, we have this create dot blade dot php, which is this file right here. And inside our post controller, we have this create method, and it's calling the posts dot create. So with any luck, we should be able to visit this new route that we just created. Have slash P and check out what It is alright. So slash p, there we go. So that is loading. Now we know that because of course, the navigation is showed up. So we're almost there. So remember, this needs to be slash p slash create. So let's do that one last change here and a web routes, slash p slash create that goes to the post controller and hits the Create method. Notice how everything is very petitive. But it follows a very particular pattern. And this is going to make your applications very, very clean, because everything is going to make sense, everything's going to have a purpose, a point. And everything's going to stay in the same guidelines. When you stay in these guidelines, it makes your application so much easier to code, and so much easier to upgrade and make changes and add features. And all of this, this is imperative, it is so important, I cannot stress this enough, it is incredibly important for you to have a very strict set of naming conventions and standards for your application, and you need to stick with them, you need to be a stickler about it, because it is for the health and benefit of your application. So with that, let's start creating this create method now. So in here, instead of starting straight from scratch, let's go to that register blade. And Let's steal some of this code that ships with Laravel. And let's grab, let's say the name. So let's grab all of this. So we see the form group and a row. And let's end right here. Alright, so this way, we are grabbing errors, and we are doing all the proper validation. Again, I'm grabbing this from the registered that blade that PHP, just for the sake of timing. So we'll have a container, of course we'll have a row. And then what I'm thinking is maybe doing a column of eight, but then having an offset of two, that way it is centered. But it is not as large as the 12 columns. This is just a design thing with them. So let's go ahead and paste this in. And let's see what kind of changes we need to make. So obviously, a label for name, not really, this would be actually be a label for the caption of our image. And let's go ahead and right here, image caption, just for now, maybe post caption, I think that'll make more sense. All right, so we have that we have that. Let's just see what happens. Let's go ahead and visit the page and see what we get slash b slash create. There we go. So post caption, and then we would write the caption of our post here. Now I'm not crazy about this right now. Let's go back here and modify this one more time. Let's see. So it looks like they do have this already. Let me get rid of that. Let's so this is what we end up with. This looks to be too far. There we go. All right, let's see what that looks like. So we do post caption, then, of course, now we do get the form. But now this is out of place. Alright, let's check that out. It's because of this text and the right, let's get rid of that. There we go. I do want to clean up this line, it's a little long for my taste, what we could do is just break this up maybe into separate lines. And I think that'll clean up this view quite a bit. So we'll leave value new and then we'll do autocomplete and autofocus, we'll leave that in one line. That way, we don't have too many. Alright, so we do need to wrap this all in a form. Actually, we need to grab this whole entire thing. So let's start right here, create a form, we'll talk about the action in just a second. we'll paste that in. And of course, no visual changes. So what else do we need? Well, of course, we need our image. So to add our image, let me add a new row here. And then we'll say input is going to be a type of file. class, we can use the file class. So form control file, then Id, of course, is going to be image. And finally this is give it a name of image as well. Alright, so let's grab the label from our caption up here. add that in. And we say this is a label for the image. For the image in post image, this is just going to be a browse so you can pick your image. And what else do we need? Alright, let's grab the error tag here as well. Looks like this is not indented properly. Let's fix that now. There we go. I'll just grab that block. And let's bring that block in here. Looks at have an extra character here. Let's get rid of that. There we go. Alright, so caption. No, we're gonna change that to image. There we go. Let's check out what we have in the browser. Fair enough. So here, you could just choose your image and upload it to the post. So finally, what else do we need Of course, we need the button to submit this. So let's add another row and say give me a button with a class of button. And let's give it a further class of maybe button primary. So it's a blue button, add new post. There we go. And we're gonna definitely gonna need a little bit of breathing room on that one. So let's say padding top three. Maybe four. There we go, that's good enough for now. So this will add a new post to our project. Finally, finally, this, just maybe add a quick title up here, let's add another row with an h1 of add new post. There we go a little large, we could definitely play around with the design a little bit more. But again, we're not super interested in the design. This doesn't even really exist in Instagram, because you can only use the app to actually add a new post. So the idea is when somebody types in their caption here, chooses an image, they should be able to add a new post to their account. Great. So let's take care of that in just a second. But we first need to talk about what were we actually going to post. So action wise, let's check out what Laravel has to say about it back to Chrome HTTP controller. So we are currently in the Create method. So of course, that is going to post to the resource, and then that's going to hit a store method. So let's do that right now. So where's that going to post? Well, we know that slash P is our resource. Finally, this form does have a file in it. So we have to make sure that we use the correct encryption type. And the correct encryption type is multi part form data. And finally, we need a method. And of course, we're gonna say this is a POST method. And where do we get that from? From right here, that's the POST method, we need to have that in our form. Alright, so we have that all set up, let me close all of that. So let me go into my routes file and make sure that that's gonna work. Let's see be alright, let's copy this, and it's not going to be a gift, but it's going to be a post. And it's just going to be slash p, for post. And it's going to hit our post controller, and is going to hit this store method. So let's go into our post controller. And create a new method here for store. And now we're inside our store method. So here, I'll just say hit. Or better yet, let's go ahead and give out the data that we are actually passing in from the request. That way we know that we received the proper data. Great. So let's go back over here. Let's hit refresh, and tell you what we're actually able to test this now. So what we need to do is actually have an image that we can test with. So let's just download one of these images here. Let me save this image as post image just for now. All right, let me save that on there. And let's go back and try out this image. So caption is going to be new caption here. And let's choose a file. Let's go into there, grab my post image, and hit add new post. And now we get this for 19. Page expired. Well, you're thinking, how's that even possible? How is our page expired? Well, it's kind of a bit of an encrypted message. But what it actually is talking about, and this is something you just need to know, if you do some Google searches, you'll find it but 419 page expired is actually a CSRF error. CSRF allows level to limit who can post to our forms. Otherwise, as you may or may not know, you could curl into an endpoint, such as that slash P and create any post that you want, without actually having to go through the website. Now, that's not particularly great, because we have no control over what people are passing in. So we need to limit who is authorized to actually hit that endpoint. And the way that Laravel does this, is by adding an extremely large key to each form. And then it can validate that key and say, Did this come from this server. And if it did, then we're good to go. But if it didn't, then we're gonna go ahead and throw this for 19 page expired, the fix is quite simple. Let's go back into our create that blade that php file. And all we need to do inside of this form, is add another blade directive, which is at CSR F. And I'll show you what that will actually add to our form. Let's go back here. And let's hit refresh one more time. And let's show the source for this page. If we take a look at our form, we now see this underscore token right here. And this is what level is going to use to actually authenticate this form from getting submitted to that endpoint. So it's very important. This is one of those security things out of the box that level ships with. And it's one of the advantages of using a framework like Laravel, it's going to force you to do things a little bit better, a little bit more secure. So this is one of those fixes. So now that we have that, we can actually write a caption here, and let's choose the same image again. And this time, it should go through and sure enough, it does. So we see that we have our image We have our token. Now one thing we don't see here is our caption. So we must have made an error here somewhere. Let's go back here. And let's check out what happened. It looks like we don't have a name for our ID field. So that's why it's not passing through. So name, we'll just say, caption. Alright, so now we have a name. And I don't, I'm not sure what this is, let me go ahead and erase that. So there we go. That's what it should actually look like. I think at some point, I added that caption equals caption, you probably saw that. That's not supposed to be there. All right, we're good to go. Let's go ahead and head back here, head back into our form, hit refresh. Let's try this one more time. And hopefully, we'll see everything we need, post image, add new post, perfect, we have our token, of course, we can ignore that that's just for level. And then we have our caption, and we have our image. Now something magical actually kind of happened here. And that is the following. If you notice this image, it actually is a class. And what level has done is wrapped that file around this uploaded file class right here that we're looking at this uploaded file class does have our image. But this wrapping has given us some tools to be able to store the file, rename the file, and even put it up in s3 or anything like that that we want to do. It's added all of this functionality to that file that just got uploaded. Now, of course, we're going to be using that in just a second. But first and foremost, I want to talk about validation. Right now, if we go back and hit refresh and just hit add new post, the form does post however it shouldn't, because really a caption is required. And this is required. So we touched a little bit on this already when we did our registration. But let's go back to PHP storm, and do an example of that now. So in my store method, the very first thing that we need to do is we need to validate our request. So we'll say our data is equal to request as a function, validate. And notice how nice this syntax is, through the request, validate that request, and then give me back all of the validated data. Very simple, very clean. So what are we validating? Well, first of all, we're going to have this caption field and that caption field is required the same token, we're going to have an image field, and it is required. Now there are some more things that we can add to this. But we'll drive that out in just a second. So our caption is required, and our image is required. Great. Hit refresh, add new post, nope, it says field is required. However, we're not seeing anything for our image, we're not getting any of the errors. Let's check out why not back to the Create method. Truthfully, all we need to do is just get rid of that span there. And hopefully that'll work. Let's hit refresh. And there we go, the image field is required. So now we're validating the request. However, check this out, behind the scenes have actually added a markdown file. Clearly, that is not an image, that's a markdown file. That should also not be allowed. However, when I hit that, all of a sudden, that is allowed. So obviously that is not correct. This needs to be an image. So let me show you something in the Laravel documentation. We scroll to the top in the search, we can say validation rules. So we can check out the available validation rules. And one of those rules is the image rule. Where is that? There we go. So image so we can say this needs to be an image. So that'll work. So I also want to add that to our validation stack. So how do we do that? Back to the post controller, so the image is required. But Furthermore, it needs to be an image. So we use this pipe notation to add as many as we want. That's one way of doing it. Of course, in Laravel, there's many ways of doing things, we can actually wrap this into an array and pass in an array of strings and say image. You may like that syntax better, because that way you could read them and it's a little bit easier to read. I do like that. So typically, I'll leave this as a string of bits a single rule. Once I get into multiple rules, then I'll pass in an array instead. And the shorthand notation makes that very easy to do. So we have required, we have image. So now if we try that again, hit refresh, choose that markdown file again, then Nope. It says the image must be an image little bit cryptic, but it's just because of the name of our actual field. But we are ensuring that an image is what's going to come through there. All right, so we are doing great progress here. So now we can start to create that post. So how do we store it? Now if you recall, when we were running through Tinker, we did something like post and then do new app, post something like that. And then we did post We can say caption equals, you know, data, caption, and then add the image. And then we can finally hit save at some point, right, we could definitely do it like that. That's how we did it in Tinker. However, there is an easier way of doing it. And the easiest way is using the Create method. So we can say, app, post, colon, colon, create. And inside this create, we can pass an array of data. And this array of data, you can pass in one at a time, like we could say caption is equal to data caption. But to be honest, this array here is this array right here. So all we actually need to do is pass in data. And that's the nice thing would do in validation. Now, if you had a field that was not going to need any validation, and you did not have it in your validation array, that field would be ignored altogether. So what you can do in that case is say, another field, just pass in an empty string. And that would be enough for level to know that this another field in your form is a valid field, go ahead and pass it through. But there are no rules for it. So whatever comes in, just pass it through, you don't have to do anything about it. Great. So let's get rid of that, as we don't need that right now. So that will create a post, but it will actually fail. And I don't know if you've kind of figured this out at this point. But let me go ahead and run it, I just want to show you what it actually does. Let's go back to Chrome. And let's write a caption here and choose an image, add new post, and we get an issue. And that is a fillable property of mass assignment issue. Now if you remember, when we added that user name in our registration, we had to go into the model and tell their vote that it was okay to do that. And I said, this is one of those things where it protects you by default, now it can be turned off. And that's what I'll actually end up doing. If we go into our post, we can actually do it in two separate ways. Now fillable fields, again, you could be explicit about them, or you can go ahead and say, don't worry about it just fill everything. Now the reason why Laravel is protecting you is because theoretically, you could just pass in request all into this right here. And if you did, somebody could go into view source on Chrome and add their own fields and pass in any number of arbitrary fields into your form. And you would try to put that into your database. But we're being very careful about each field and we are naming each one. So as long as you do that, it's okay to turn off that feature. So let's go into posts and turn that feature now. So we can override the garden that's protected, guarded, and just pass in an empty array. So if we say protected, guarded equals empty array, then we are telling Laravel, it's okay, do not guard anything, everything is okay, kind of leave me to my own devices. And I will take care of it myself. So with that, we're going to get another error. And it's going to be a different one this time. But let's go ahead and hit refresh and see what happens. Now we get an integrity constraint violation. What in the world is that? Well, if you remember, let's go back to PHP storm, when we created that post table, we do have this unsigned, big integer for user ID. But nowhere in here, are we actually passing in the ID, right? The ID is actually nowhere in the request, because the ID is supposed to be the ID of the authenticated user. However, right now, if you remember, we may not even be signed in to the proper solution is to save through the relationship to create through the relationship. So let me show you how to do that. Now. Let me start writing it up here at the top. So how do we get the authenticated user, the easiest way to get the authenticated user is to use the auth function. And we'll say off, give me the authenticated user. And on that user, I can call the posts. Remember that our user go back to the user model. The user has this post relationship, and it has many so it knows about these posts. So we can say posts, but this time, we're going to put parentheses on it up until this point, whenever you've seen posts, we haven't added the parentheses. This one does need parentheses. So we can say posts and then arrow function again. And then to that we can pass this create right here. And that will be able to do what we need it to do. What that will do is it'll grab the authenticated user, it will go into their posts and create. Now Laravel behind the scenes is going to add that user ID for us because it knows about the relationship. So we can do that for us automatically. We don't have To tell them about my user ID is ID one or two or three levels going to take care of that for us. And that's pretty cool. However, this is going to fail again. And the reason is, I'm actually not signed in. So you see, we get this post, or no solution for that, of course, is we need to be signed in. And we're going to protect against this, of course, at some point, but for now, let's go ahead and sign in and make sure that we are authenticated. It says not found, that's okay, we removed that route. So let's go into p create. And this time, I think it'll work. So let's go ahead and pick a correct file, post image, add new post. And sure enough, we did save that to the database. So let's go into Tinker real quick to prove that. Let's see post, grab all of my posts. And sure enough, it did save that to our database. Now, notice here, user ID is set, even though we actually didn't have that anywhere in the data that we passed into that create method. But because we actually fetch the authenticated user, and use the posts relationship, that's how we were able to create a post on our user without actually telling Laravel which user it was. Now this works, because of course, posts can only be saved to the authenticated user, you cannot create a post in somebody else's username, right? That doesn't exist. That's not the correct functionality. The correct functionality is that only the authenticated user can actually do that. So now let's talk about this for a second because we were not signed in, yet we were able to see this. And that's not even right. So how do we fix that? Well, there's actually a very simple solution. And that is to use the middleware, the auth middleware. And so if we go, if we add a constructor to this, we can say this middleware, and all you have to pass in is the auth key. So from here now, if on a controller, you have a constructor with middleware of auth, then every single route in here will require authorization. Let's check that out in action, let me go back here. So we can obviously see this create. So I will log out. And now I'm going to go to slash p slash create. And now it actually sends me to the login page. So now that route is protected that route. And of course, the post route, both of them are protected, because we added it to the whole entire controller. So cool. Let me sign in again. And there we are. So now we can see the form. And of course, we can add a new post to that. Great, but now we're not properly handling this image. If you take a look at Tinker, it put it in somewhere in private variable, obviously, that is not correct, we need to upload that image. And we actually need to resize it and fit it to a specific constraint because Instagram is actually square. So we're going to take care of all that all in one big step. And it's going to be very simple, I think you're going to really like it. Okay, so back to PHP storm. And let's check this out. After we validate our data, then we know we're going to have an image. So remember that that image is actually going to be an instance of uploaded file, which is a class, that level wraps any files that get uploaded into automatically. So let me show you that. If we get our request image, let's check out what happens in the browser. Let's go back here. Let's do it one more time, any text will do. Grab our image, and hit add new post. So there we are, we're getting this uploaded file class. Now this Upload File class, like I said, adds a lot of functionality. And the nicest thing with that is that we can simply call a store method on it and pass in where we want to store our file. And we don't have to worry about the difficulties of PHP having to move files and relative paths, and none of that you don't have to worry about anything like that. So we said request image, go ahead and store it. That's an available method in there. Now as a first parameter is going to take the path where you want to store it. So if we left that just as a slash, that's just going to put it in the root of our storage path. However, I actually want to do that in an uploads directory. So I want to create an uploads directory and then any images that get uploaded, they're going to go inside of that. Now as a second parameter, it's going to take what driver we want to use to store our file. Now, we haven't talked about drivers and file system or anything like that. But just know that there are different drivers for you to use. One of the drivers is an s3 driver, which of course is for Amazon s3. So we would say s3, and if you have all of your credentials, properly saved level automatically upload the file into Amazon and bring back the file name. So that's that easy in our case. Now all we have is just our local storage. So our local storage is going to be in our public directory. And I'll show you all this in action in just a second. So let's go ahead and run this code one more time. And what I want you to notice is here, let me open up this tab again, that file is going to end up inside this storage directory. So let's just refresh the page and see what kind of changes we get. Refresh. So now we see that we get a file path, as opposed to the instance of uploaded file like we had before. And back in PHP storm, check this out. If we open up app, public, we now have this uploads directory. And inside of there, sure enough, we have our image. So Laravel has moved it for us. However, where it moved it to, it is not accessible to the public, this public directory inside of storage is actually not accessible for us to be able to tap into that file, like so let me show you. So back to Chrome, if I copied this, right, you would kind of expect to be able to say whatever our domain is slash uploads slash and then our image name. But if we do that, it's not going to find that right. So we have to be able to tell Laravel, go ahead and link to those files that are inside our storage. Great. So how do we do that? Well, it's actually quite simple, there is an artisan command for that, you will only have to run this once in the life of the project. So if we run php artisan, we have this storage link. And what it does, it creates a symbolic link between public storage to our storage app public. And that's where our file actually is. But we needed to be inside the public directory. Remember, the public directory is what's actually accessible to the public, nothing else is accessible. So let's say php artisan storage link. And that's it. Now it created. So just like that, if we go back to Chrome, now, we're not going to be able to run uploads, we actually do have that inside a storage. So it'll be storage, slash uploads, and then that file, and there we go. So there, we do have our image. Great. So you have a couple of options here, you could do that on the fly, you could add that storage on the fly, because if you remember, what actually came back did not contain that storage, we're going to do it on the fly. But you could always add it to the database itself, we're not going to do that. So let's go ahead and save this. So this right here, that's returning our file path. So let's go ahead and save that as image path. So that will be this string right here. So it will be the string that we actually want to put into our database. So now that we have this image path, we actually can no longer just pass in the data, we are going to have to go to the manual version of this. And we're going to say all right, the caption is going to be contained inside our data at the key of caption, so far, so good. But then our image, what we actually want is the image path, which is obviously what we saved from creating that request. Now, after we hit the store method, it's going to die and dump and just give us everything. What it should really do is it should redirect. So let's say return a redirect, where do you think we should go? Well, we should really go to the user's profile, profile, slash, and then we need the authenticated users ID. So let's just concatenate this for now we're going to fix all of this up, don't worry, it's going to get even more clean after this. So we are going into our authenticated users and grabbing their ID, as that's really it. Remember, this door method can only be hit if you are authenticated. So we can safely grab the authenticated user, no one that is not authenticated, is going to get through because of this middleware that we added here for this controller. Great. Let's try this one more time. So refresh, hit Continue. And sure enough, we get back here. Now it did work. However, we haven't worked on our view yet. So we are actually not displaying the proper images and posts for this user, these three images here, we added in manually. So let's go ahead and do that. Now. Let's work on our view. So we can actually see what happened behind the scenes. So let's jump back to PHP storm. Let's go to our index that blade that PHP for our profile. So here in this row, we obviously have the three that we added just to see what the design was going to look like. So what we can actually do is say, Alright, for each. So how do we get the data, we have our user, and we know that the user has posts. So we can call that relationship, we'll say user, give me all of your posts as post and for each and then what are we going to output in here? Well, it's going to be something very similar to this. We're going to paste that in. We're going to of course, replace some of this stuff right here, as is not all necessary. So we'll say our posts. We need your image and that's going to be the public And then we do have the caption. We just don't have that just yet. So we'll grab the image. But remember that this needs to be slash storage, and then slash uploads. Everything else that's in there. We'll grab that for now. And that should work. Let's see, refresh. Sure enough, it does. Now remember, there was that one image that we added first, that was not correct. So we actually should truncate this and try it from scratch. So that's what I'll do. I'm going to delete all of the posts and start from scratch. How would we do that? And well, easy enough, let's go into Tinker. And let's just say, post, truncate. And this will erase everything in the post table. So now if we go back to Chrome, hit refresh. There's nothing there. So we are fresh, there are no posts, right? Now, let's add a new post. And that reminds me, when we hit that it actually doesn't work, we need to link to our actual create method. And let's find that a new post right here, we haven't told it where to go. So that's going to slash p slash create. Let's try that now. There we go. So this is my first post Free Code gram. And let's choose an image and choose Add new posts. And there we go. So we are successfully uploading a post, let's do another one, let's say my second post, choose a file. I'm just gonna choose a logo file here at new post. There we go. But now we notice a bit of an issue. And that is, it's actually ordering them by the upload in sequence. But in Instagram, your latest posts go to the front. So it's actually inverted, we need to change the order to make it a little bit more obvious, let me go ahead and add a third post right here. That way, it's really obvious. And I'm even going to add an image that's going to throw everything for a loop, a happy screen. So obviously, the happy screen is not even the correct size, we're going to handle that in just a second. So that's why I brought that image in. So the order should be happy image should be first, then decoders tape, and then this image, because that's just the way the Instagram ordering works. So let me show you how to do that. And it's quite simple in Laravel. If we go to the user model, after we have this has many, we can tag on an additional call. And we're going to say order by created ad. and in what order, it's going to default to ascending. So let's go ahead and tell it descending order. Now the created Add Column gets added for us automatically. And I'll show you where that is. If we pull up the Create post migration, right down here, you see this table timestamps. If we click through to that, you see that that adds two additional fields, it adds the created at and updated. Both of them are nullable. But they are going to be updated for us automatically in the database. So that's one of those nice level features. So we can just simply assume that there's a created that and just call it descending. Alright, back to Chrome, refresh. Boom, there we go. So now we are in reverse order. What else do we need to fix here? Well, there is this count right here as 153 posts, again, another number that we hard coded, we now have an actual count of posts. So we can change that number for the actual number back to PHP, storm. And in our index, let's find that 153. So what do we do with 153, we'll say user posts, just get me the count. Let's go back to Chrome. Refresh, there we go. So now we have three posts. Great, let's add a fourth one. So we can see that number change fourth post, I'm gonna have to repeat an image, I don't think I have any other ones. So add new posts. So there we go. We have four posts. we'll tackle the rest of these as we go along. But now we are making progress. We are really hammering this code out. That's great. Now another thing here that I noticed right away is, we do need a little bit of spacing between these lines. So we do need a little bit of padding at the bottom of each one of those. So we'll say call for padding, bottom, maybe for refresh. There we go. That looks great. So what do we tackle next? Well, everything kind of needs to fit into a square. Now there's a fantastic PHP image library that will allow us to resize and fit the images that get uploaded into a square automatically. And it's very, very simple to use. Now we do need to pull in an external library. So this is going to be a nice sequence for us. We haven't pulled anything in that did not come with Laravel. So it's time for us to tackle that. Let me exit out of Tinker. And so how do we bring in a new library? Well, of course we're going to use composer, composer is our dependency manager. So with composer we're going to say go ahead and require and the package is intervention. slash image. This intervention image is actually a nice PHP library that has some integration with Laravel. Let me actually pull up the documentation. And I encourage you to pull it up as well, because intervention is kind of the place to go when it comes to image manipulation in levo. So intervention image, the website is image, the intervention that I Oh, and as a basic example, this is what they give you. And finally, if you go to the installation, all you're going to see there is kind of the same thing that we just did is just that composer require intervention slash image. Now for Laravel, it does have a specific level integration. And if we look back here, it's done installing. But what we find here is that it discovered the package automatically. This is a feature called package auto discovery, it was introduced to Laravel, a couple of versions ago. And what it allows is a package to hook itself up into our application, without us having to explicitly tell Laravel, about any of the packages. Now, not all packages have opted in. But at this point, it is kind of imperative, if you write a package that has a level integration, you kind of want it to be auto discoverable, the way intervention is, in the past, we would have had to go into our level configuration, and tell Laravel about this intervention image package. But now that's no longer needed, we see that it was automatically discovered. And that's just great news for us. So we can start using it right away. Let's go into PHP storm here, back into our post controller. So after we do that to our image, let's go ahead and resize it. So let's say image equals, and we can bring in our package image. If we look down here, we have this intervention images, facades image. Now notice up here that did get imported automatically, this line up here got added automatically by PHP storm. But make sure that you have that in your project if you're following along. So us intervention image facades image. So whenever we're referencing this image class, it's not really image because this class is actually under a different namespace altogether. So we need to make sure that we're grabbing the correct image. That's very important. Otherwise, you're going to get an error, saying something like the image class was not found. If you do, that's what it is, you're missing the use statement. So we'll say image, make me an image. And what make an image we'll do is wrap our image file around this intervention class so that we can start to manipulate it. So where do we find our image file? Well, we can use that helper and the public underscore path helper. And to it, we can pass in our image path. Now our image path is storage, slash, and then our actual file, so we can say, image path at that point. And that's where image is reciting. Now, how do we resize? Well, there's a method in the intervention class called fit. And fit takes two arguments, and they are pixel counts. So this would be the width and this would be the height. So what this will do is it will take our image, it will wrap it around the intervention class, and then it will fit it to 1200 by 1200. Now, this is different from resizing, because resizing will change the physical dimensions of the image, proportionally, in our case, we kind of just want to cut the image, we want to cut any excess that it has, and fit it to a 1200 by 1200. square image, we do want every image to be 1200 by 1200, no matter what. So once we've done that, well, we need to save our image. So it's as simple as just calling the Save method on that image. And we are good to go. So let's give that another go. Let's go back to Chrome. And, in our project, I'm going to bring in this image again, notice how the first time we brought it, it is not completely filling up the square. Let's try that same image one more time. So test screen, square, choose an image, happy screen, add new post. And there we go. So look at the difference. This, this over here, of course was before we added the fitment. And this one over here, of course is now that we've fitted that image to a particular square size. So this is a great way for us to grab our image and resize it. This is another way that you can also create thumbnails. If you're needing to create thumbnails on the fly as you go, the intervention image package will be able to do that for you. You can select say 300 by 300 thumbnail and then have your original image. In our case, we don't really need to do that. So we're good to go. Now, what do we need to do next? When I click on one of these images, of course, I want to be able to see the image and the caption for that image. Alright, let's do that. Now. I'm going to close everything up. Just to clean it up. Let me go to the end. index that blade that php file. And let's find this image right here. So this image obviously needs to be wrapped in some sort of anchor tag. So let's say anchor. And we'll talk about where it's going to go in just a second. And let's hit paste. So let's talk about where that image is going to go. Because of course, we need to refer back to our resource for controllers has go back here a couple of times, and let's find those verbs one more time. And there we go. So we did the Create, we did the post. And now we need to do the show method. So the show method is the one that shows one particular resource. So in our case, it will be slash p slash the ID of our posts. So how do we grab that? Well, it's actually quite simple. It's going to be something like slash p slash, and then we need to pull in the post ID. All right, let's go back here. And let's see what it looks like. If you notice down here, right down here, as I hover over, you see that that says, slash six. So if we click through that, of course, that is not found. But we know that we need to make that route work. So it's slash p slash an ID, back to PHP storm, let's pull up the web dot php file. And let's create a new route. So it's going to be a get route slash p slash, and what are we pulling up while we're pulling up a post, so let's put in a variable of post, that's going to hit our post controller, and it's gonna hit the show method. All right, let's create that now, post controller. And let's put it right after the store method, new public function show. And that's going to take a post, because it's going to give us the post ID. So in here, I will just output post for now, because we still need to create the view for it. So let's go into our views. So in our posts, we have this create that blade, let's save as, and let's create a show that blade that php file. Now this show that blade that php file, of course, everything needs to kind of go for the time being, I'll just write in show. Alright, hit refresh, and there we go. So we are properly passing in post of five. So if you remember, up until this point, while we're looking at the profile controller, we actually fetch the user manually. But Laravel does have a much better way of doing that. And it's called route model binding. So check this out. This right here, right now, as you remember, let me check it one more time, all you're getting is just the ID, whatever you're passing in right here, that is just passing through write, nothing special there. But with one small change, we can kind of make a little bit of magic happen. So this is the way it works. If this is called post, and in your post controller, this variable is also called post exactly same thing. Then if you type hint in the model, then level will actually try to fetch that resource for us automatically. Check this out. So let's say up post. And by just adding this, let's go back to Chrome and hit refresh. notice a difference. Now level is actually fetching our posts, automatically, we are not needing to do anything else. But even better than that, you remember when we had to change from find to find or fail, remember that we were in our profile controller. And we have to change this from find to find or fail. Remember that? Well check this out. It also does that for us. If we change this from five to blah, yep, we get the four four not found, the Lego is doing everything for us. All we simply need to do is tell it, this is the model that I want you to fetch from now now we have our post, it's available to us, we could just assume that it's there, or Laravel is going to respond with the proper 404 not found error. So what do we do here, all we need to do is return the proper view. So that's going to be inside posts dot show. But we do need to pass through the post. Now if you remember, we passed in an array before. So we'll keep doing it like that post. But there is a small shortcut for this. Now this is how we did it before. But check this out. There is a function called compact. And to compact we can just pass in post. So this is the exact same thing. It will match post equal to a variable of post. That's it. And you can pass as many strings here as you need. So if we had another one, that was another field, you could pass that like so. Obviously, we just have our post. So now inside our show, we can say give me an image and the source is going to be post image. Now this does need to be slash storage slash our image. So let's check this out, refresh. Notice, we have our happy image right there for that post, let's go back to our profile, let's visit this page. There we go. So that's working just fine. Let's work a little bit on this show view, obviously, we're not going to just slap an image in there. So let's say a row and inside of it, maybe have a column of eight and inside of there, then we'll have our image as a class, let's do wide of 100. That way, it adjusts properly. There we go. So that's looking good. Three, let's go to let's go to this one right here. Here we go. So that's looking good. So I want this to look a lot like this page right here. So I do see that they're using the logo here of the user account, we don't have that set up just yet. So for now, we'll just have the caption. So let's just go back, and let's add, maybe an h3. And let's have the username in here, post, grab the user, and then grab their username. Let's go back. There we go. So test username. And finally, let's add a paragraph tag. And we're just gonna echo out the posts caption to post caption. Refresh, there we go. So this is my first post. And of course, if we go back, and let's click on a different one, test, green square. So we are successfully showing that now this image here is quite large, I can't almost fit it. But again, we're not worried about the design too much. So let's go back here. And let's keep chipping away at these different functionalities. So we've made a lot of great progress. So we're now able to add posts. And of course, if we created another user, we could also create more posts for that user. So that's great. Now one thing we are unable to do right now is edit these fields. As a matter of fact, this image right here is also a profile image that we're going to want to upload, and all of that. So let's do that. Now, let's do a edit view for our user. So let's go back here. And let's see what we can add that in my index, somewhere down here underneath add posts, let's go ahead and create a new Edit Profile link. There we go. Now that I'm not crazy about that, let me actually move it out. That way, it's just sitting there at the bottom. That, of course, is only going to be shown if this is your profile, or otherwise, this should not be shown. So we're going to start talking about roles, how to restrict access to certain parts of applications and all of that. And so this is going to be an awesome section of this tutorial. So Edit Profile, where should this go? Well, let's go back here. So as the name would suggest, we need to go to Edit. So the link will look something like slash profile slash the user ID. So in this case, let's say user ID slash edit. So what will that look like, let's go back here, hit refresh. And if we do that, then of course, we hit the profile slash our ID slash edit. Great. Let's go back and make that route right now. Web dot php. And so we have this one right here, we're going to add a new one, that's gonna be slash edit. So that will go to the Edit action, and profile that edit. Now these names that we're adding to this one, we're actually not using them right now. But we can and of course, I will show you how to do that. But for now, just change that to profile dot edit. So we have our profiles controller, and we need that new edit method. So profiles controller. And let's add a new one, public function edit. And in the Edit, we of course, are going to receive a user. So our user right here, if you remember is being passed in through here. Now in the previous lesson, of course, we grabbed our user like this, but I just showed you the easier way of doing this. So let's do that. Now. Let's actually have an app, user, and user. So that will give us a user to we're actually able to refactor this as well, instead of us actually finding that user, let's just let level do it for us. So we'll say app user user, and we can get rid of that line altogether. Furthermore, we can refactor this as well to the new compact function that I showed you. And we're just going to pass that user through. So same thing here. Let's return a view. And the view is going to be profiles dot edit, and compact as pass through the user. And that's it. Look how simple and clean this is. Now this of course, we are importing it up here at the top. So we actually don't need to have that at all. We can just simply say user, and again, it's because we are importing this at the top. If we did not have this line, we're going to get a user class not found err so Make sure that you have one of the two. Okay, so now this edit, we don't have that, let's go ahead and make that now. So let's copy the index dot blade, and create and edit that blade, edit that blade. And that's going to be inside our profiles directory. And as we've done before, let's get rid of all of this container. There we go. Alright, let's go back here. And now we are working again. So we are able to fetch that. And just to prove it, I'm just going to echo out the user say ID. There we go. Of course, we have a user with ID of one. So let's go ahead and copy some of the code that we had before in our create method, as is all mostly repetitive stuff. So let's go ahead and just grab, you know what, let's just grab all of it, including even the form action, I'm just gonna copy the whole entire thing. And let's bring that into here. And let's start to edit through it. So form action. Well, we're not going to be posting to slash p anymore, let's check out where we're actually going to post. Now this we haven't done yet, because we have not edited something. So it's a little bit different than just posting to the resource. In our case, we're actually going to put a put or patch request to the resource slash, and then the ID. And that's going to call an update action. Now put or patch, which one do you use? Well, I personally like patch, I feel like the word patch feels more like updating, where put feels more like inserting, and because we are not inserting, but rather, we are updating. That's why I use patch. So we'll stick with patch, we do have to trick the browser's because there is no such thing as a patch verb, you can only put GET or POST. So we're gonna have to trick them a little bit to get that patch, or even delete to work. So we'll get to that in just a second. So now that we have that, let me see what we have here. So we're going to post to slash profile slash and then the user ID. So user ID. Now, this is not a foreign data multiparty just yet. But we do know that we're going to have some sort of profile image at some point. So I will leave it as a multiport. Now for method, we will leave posts, you don't really have an option, you can't put patch here, that will not work, it will actually default to get. So what we could do is using one of the blade directives, we can say the method is actually patch. So even though we're posting through method of post, we're actually going to use the method of patch internally. Now we don't have that route just yet. So let's create that now. Let's say patch instead of put. And that's going to be to slash profile slash user. And that is going to hit the update action. So we've changed that in both places. And now we have our route. So this will show the form. And this will actually do the process of updating our record. Now we don't have that update just yet. And that's okay, we're still working on the form. So let's change the title to edit profile. And let's see what we need here. Well, we're going to have a label for title. And we'll say, title right here, title. And then let's create another one, for description. And let's create one more. And that one is going to be for URL URL. Alright, let's see what that looks like on the browser refresh. So Edit Profile, we still need to edit our fields. But we do have three of those. So let's go back to the first one. And this one is going to be title, that is correct. The second one is going to be description. And then this third one is going to be URL. Okay. See what that looks like. There we go. So we have Title, Description URL, and then we have the rest of our form. Now this post image is not going to be an image, we know that this is going to be a profile image. So we'll say profile image for now. And if it has errors for image, that's all okay. So finally, let's do save profile. feel like that's more appropriate. There we go. So save profile profile image. Alright, so we pretty much have our form. However, there are some things already filled out for us. If you remember back in our profile, we are pulling cool title description and free code camp.org. But that is not being put into our edit. When you hit Edit, you expect this to be prefilled with whatever the current value is. And right now there is no current value. So let's make the change to our code to reflect that. Back to PHP storm. Let's start with the title. So right here, we are setting this old title. And what old title actually is, is when you fail validation, and you come back, you do expect those fields to be populated with the data that you entered. And that's what old is going to provide us. But in our case, we need to pass in another one, just in case old is not set, then go ahead and use then whatever is inside my current profile. So I'll say profile title, hit refresh back to Chrome. And now we do have cool title. Alright, let's do the same change to all of our other fields. So old description, that of course, it's going to be description. And finally, old URL, or the current profiles URL. There we go. So that is more of the functionality that you are expecting. Cool title, description, and Free Code Camp are the current things in our profile. Great. So now let's do a little bit of validation. Again, if you hit Save profile right now, the first thing we're going to say is update is not available. So let's go ahead and add that in. We'll go to the profile controller, and add a new method here for update. Alright, hit refresh. And now nothing happened, because obviously, we are not doing anything here. Okay, so what kind of validation do we need to do, let's do the same thing we've done before data equals, request, validate. And to validate, we need to pass in an array. So we know that we're going to have a title, we're going to have a description. And of course, we're going to have some sort of URL. And finally, we are going to have an image. So all of that in there. If we actually die and dump data, the array, we should be able to see what we're actually getting. And there we are. So we're getting title, description, and URL, it looks like image obviously did not come through because we didn't add an image. So really, there isn't a ton of validation that we need to do. The only thing is that we wouldn't want somebody to maybe delete their title or description, maybe will only allow them to delete their URL. So in that case, we need to say title is required. And maybe the description is required. And then as a URL, let's see if there's a validation rule for that. Let's go back to the documentation available validation rules. And let's see if there's something for URL. And sure enough, there is. So this will mean that it needs to be a URL. So we hit Save profile. And of course, it says that the URL format is invalid, because of course it is expecting http colon slash slash Free Code Camp. org. There we go. Now that passes validation. Great. So that's working out pretty good. But when I hit Save profile, of course, it doesn't save, it doesn't really do anything. So let's take care of that now. So all we need to do is, of course, in our update, we are fetching our user, it is being passed to us, we just need to accept it up here. Now there is something to be said about what I'm about to do. So sure we are passing a user right now. But that user is kind of exposed right here. So we're going to do it this way. However, the safer route is to actually only save to the authenticated user. So I'll show you both ways. So we can say user, but the information that we have here is actually for the profile. So we can say user profile, go ahead and update all of these fields that are being passed in. And then when you're done, let's go ahead and return a redirect back to slash profile slash, and then what do we need, we need the user ID. So user arrow ID. Alright, right. Let's see that in action. Let me hit refresh on this. And let me just type in HTTP, colon slash slash, save profile. And now we get a fillable. So let's go back to PHP storm. And let's go to the profile model. And what we see here is that we actually haven't put anything. So let's override that guarded. One more time. So protected, guarded, equals empty or rank. Again, this is disabling mass assignment, that protection that we get out of the box, we are disabling. And again, we are doing this because we are being very, very particular about how we bring in each of these fields. We're not just passing in the entire request into the update. So let's go back and hit refresh. and with any luck, we change it and sure enough, we did. Alright, let's change the title. So cool. Title two, and then description. More, for example, save profile. Yep. Cool title to description more. Great. So that is awesome. But this brings us to the next point, we'll talk about the image Just a second. But check this out, I'm going to open up this in in incognito window. And in this incognito window, I'm going to visit this profile. And even though I am not logged in, we are still able to edit the profile. So Matter of fact, if I hit Edit Profile, and I tried to save the profile, I technically could do that. Even though I'm a guest, check that out. So I was able to do that as a guest. So we're gonna build protection for this. But before we even get into the policy protection of it, one easy thing that you can do is to always revert back to, instead of just grabbing whatever the user brought in, whenever you're going to do an update, or delete, or an edit or anything like that, instead of just trusting what the user gave you. Because technically, I could go in here and type in whatever number I want, say, user 123, obviously, in our application that doesn't exist. But 123 could be an actual user. And that user may be able to do that. So instead of grabbing that user, the other way is to say off user, and this is going to force an extra layer of protection. And that is that you are only grabbing the authenticated user. And it doesn't matter what they're giving you through the query. So we are going to protect this with a policy. But I still want this in place as an extra layer of protection. So let's go back to Chrome. And I'm going to try to edit this profile one more time. And when I hit Save profile, it fails, of course, it is not able to grab profile, because that user does not have authorization to do that. So now we've added a little extra layer of protection on that. So with that, it's time for us to start tackling a policy, because this edit profile should not even be showing, because if you are not the correct user, then that should not be showing. So when we open that in an incognito window, or as a different user, you should not be able to do that. So for that we use policies. So policies are a very simple way for us to restrict what a user can or cannot do with a particular resource. Now policies are associated to a specific model. So in our case, we can say, we're going to do a policy for the profile. So let's go back into our terminal. And let's run php artisan, and check out the make policy command. And there it is. So make policy. So this creates a new policy class, let's run PHP, artisan help make policy. And it looks like we need a name as required. But we can pass in a model, great PHP, artisan, make a policy for profile policy. And the model is going to be profile. Alright, let's check that out. Go back to PHP storm. Now inside our app directory, we do have this new policies directory. And inside of there, we do have this profile policy. Now, each of these methods in here represents an action that can be taken on this particular resource, in this case, a profile. And it's all based around the user, the user being the authenticated user, that you have right now. Now, out of each of these methods, you have to return either true or false, meaning that the user that was passed in can view the current profile. If you return true right here, if you return false, then that means that that is not correct. So with that being said, we do have view we have the Create. Now, the Create method, of course, does not have a profile attached to it, because there is no profile is being created as we speak. So that would be more for being able to authorize, say, admins to only be the ones that can add profiles or something like that. An update, we have delete, we have restore, which is for when you use soft deletes. And then we have the force delete. So how do we put this to work? Alright, so obviously, we are talking about updating. So how can we determine if somebody meaning a user can update the profile? Well, that's actually quite simple. We need to return user ID equals the profile user ID. Does that make sense? So this user's ID for the profile needs to match the users ID meaning they own that. So now let's authorize that. Let's go back to the profiles controller, this edit right here. Let's actually authorize this action. So to do that, we'll call this Authorize. And what are we authorizing? We're authorizing an update on this particular profile. So let's say user profile. So we're going to authorize an update and then all it needs in here is a profile so So this edit view is now protected. Alright, so let's see that in action. Let's go back to Chrome. Let's hit the Edit Profile. And sure enough, we can see that view. Now I'm going to copy this URL right here, and I'm going to log out. And let's try to visit that now. Nope, can't do that says this action is unauthorized. So we are properly actually doing that. So that's great. What else do we need to protect? Well, we actually need to protect other routes in this same controller. So let me copy this. So the update, this should also be controlled, you cannot hit this unless you're authorized to update. So Furthermore, we do have that lingering link. So let's go to the profile. There we are. So we still see this edit profile. I'm not even logged in. So clearly, that is not correct. So let's fix that. Now, back to PHP storm. And we have a really nice blade directive that we can use. So let's wrap this in that blade directive now. So we'll say can if the user can update. And we have the user. So let's pass in the profile very similar to what we did in the controller, and can, so that will give us a true or false and it will authorize this link right here. So let me hit save, head back to Chrome, refresh, boom, it's gone. But if I log in, and say test at test, comm, login, let's go to my profile again. Now we can't see Edit Profile. How cool is that? So we are restricting access to this page, and even to the safe without having to do much at all. So of course, let me log out let me create a whole nother user, I only have the single user right now. So other user, other at email, com, other username, register. Okay, so let's visit that user's profile. Even though we are logged in now, we still can't see that edit. And as a matter of fact, we also can't visit edit. So it's not because we're logged in or out. Because right now, obviously, we don't see that and we are in. Alright, what else can we handle? Well, there's this add new post right here. Now we are in the test username profile, yet, we can see the add new post and I am logged in as other username. So clearly, that should not be true. So let's think about this for a second. How could we restrict that? Well, the easiest way really would be, we're only going to show that if the customer is able to update their profile, meaning that it's their profile, so we can reuse that logic. So let's take a look at that right now. And let's see. So add new posts. So all we need to do is really this exact same thing. We just need to bring that up here. And then let's replace that link with this link down here. refactor that, get rid of that. Alright, let's go back refresh. And now it's gone. Let me log out and let me log in as that test username. And see test at test Comm. And there we go. So this person can add new post. So now we get to this page right here. And it looks like we are getting a 404. Let's find out why back to PHP store. Let's start with our routes file. P create. Alright, so this is not working, right. But this was working. And this is very interesting. Check this out. So this route right here, and this route right here. They are conflicting. And the reason why they're conflicting right now is because this one is taking anything that comes after the peak. So because it's doing that, we need to actually move this route. This is an important point. And I'm glad we ran into this issue right now, you need to be careful with the order that you put your routes. Because this is different than this. If we move that row down, then this begins to work again, let me prove it. There we go. So we can add new posts. But if this create is after this one, then of course, this is going to match first, and it's never going to get to this line. And to prove it, we can just go back and refresh. And now we get that 404. So just keep that in mind. Sometimes your routes need to stay in a particular order so that they properly work. Obviously anything with a variable like so should be kind of at the end. That way it matches all of your actual routes. And then if it doesn't match it, then it's able to do something more dynamic. So keep that in mind. I'm glad we ran into this because this doesn't happen often, but it does happen. So we have add new posts that is working. And of course our profile is also working and we can add a new post. Alright, what do we want to tackle next? There's a couple of things that we can tackle. But we have this lingering image right here. Up until this point, this image has actually been hard coded. Let me show you We're going to PHP storm, let's check out where that image is coming from. And it is right here. So notice that that image is hard coded. What we want to do is really be able to edit the profile and start to use this profile image right here. So how would we go about doing that. So let's go into the profile controller. Let's check out this update. So right now we are grabbing the image, but we're not really doing anything with it at all. So let's do something, let's do the following. If the request has an image, now we're going to do something special. Now the reason why we have to do it this way is because sometimes the user may just click on Save profile without choosing a new image. If they don't choose an image, then we can just assume that the image that we already have on file for them is fine. Go ahead and keep using that old image, we don't want them to be required to give us a new image every time that they save their profile. So only sometimes are we going to do that. So if the request has an image in that case, then we need to do something very similar to what we did in our post controller. Let's check that out. Back in the post controller, we have this section here with the image path. And how we remake our image, I'm actually going to copy this right into here. And we're going to say alright, the image path is going to be request image. So now instead of uploads, let's put them in profile. And we're still using the public driver. Great. So now we're going to take our image, we're going to grab it, this time is not going to be in storage, it's going to be under profile, image path. And let's go ahead and fit it to maybe 1000 by 1000. That way, everybody has the same constraints, then we're going to save the image. And we're almost ready. However, at this stage, we've already updated our data. So we actually need to push this down. So that we do a single update on that. And let's do something in the data, we actually are going to need to change this image because right now image would just be a regular image, but we need it to be the image path. So we need to revert back. Or we could do a little trick, check this out. There's a PHP function called array merge. So array merge takes any number of arrays, and then it appends them together. So something cool kind of happens if we put data first right data is going to be this array right here of data. And then as a second argument, will pass another array with the key of image that will override whatever was in the key of image in our original one. And I will actually show you that. But give me one second, let me finish setting this up. Alright, so check this out. I'm going to die and dump very quickly here and say data, so that you can see what we have under data. So let me choose an image. And I'm going to hit Save profile. So it's saying that image is not found. Of course, we did not import image. So we need to import image, import that class, that's going to be intervention image, facades, image, and that's being imported up here at the top. Hit refresh. Image short, not readable. Let's see what's going on here. Public path profile, you know what, yep, this needs to remain storage, because storage is just where we're going to have inside the public path. So I changed that by mistake to profile that needs to remain storage. And let's see, there we go. Alright, so now this is our array. So this array, notice how the image key on this is that instance uploaded file. However, if we die and dump this array merge right here instead, let me copy that out, Miss Diane dump that instead. Notice what happens again, this is the old data. So we have image equals two uploaded file is hit refresh. And now we have image is equal to the correct image name. So what happens is that this data array does have a key of image, but the second array overrides that image. So that's a pretty cool way that you can merge two arrays together. So this is good to go. However, let's visit the create profiles table. And we don't really have anything for image. So we actually ran this, we'll let it run. We're gonna get this error, which is obviously that there is no image because we never accounted for an image in our profile. But that's easy enough, we can make that happen. We'll say image knowable, and we're good to go. But that kind of breaks everything because now we're going to have to migrate our database from scratch and we're gonna have to start over. So let's do that very quickly. php artisan migrate fresh. This is going to erase everything. And we're going to start from scratch. As soon as I go back and I hit refresh, everything is gone. Alright, so let's start over really quick, let's register our user one more time test user, test the test, Comm. Password. And that will show you a better, more convenient way to actually do this. But we are also about to run into a different issue. And that is that, remember that when you create your user, we are not creating a profile for them. So when we get to this page, technically, there is no profile for them. So as part of our registration, we really need to create kind of a blank profile for our users. That way, they can start using it and they can edit it. But right now, because there is no record for that user on the profiles table, this is what's happening. Now there are, of course, a couple of different ways that we can fix this. But what comes to mind is something like this. So in our user model, wouldn't it be cool if we can hook up to an event, right? Something that says, hey, I am creating a new user, is there anything else that I should do, when that'd be cool? Well, of course, there is such a thing. And the way that it works is there is this method is called boot. And this boot method is really what gets called when we are booting up this model. So if we override that method, we definitely still want to call the parent boot. But then we can say, static. And we can say created, created becomes an event, right? So this created event gets fired whenever a new user gets created. Let me show you that in documentation, because there are a couple of different events that you can hook up into. So let's go back here, we need to go to eloquent model events. And right here, eloquent model events. Alright, so there are several different events that you can hook into retrieved creating created difference between creating and created, is creating gets called before it actually creates the record and the database created is after it's done, updating, updated, seeing things saving and saved. Same thing. So you get an event before and after every different type of thing that a model will do. In our case, we're interested in this created, right because when a user gets created, we also want to create a profile for them. So this is the best way to hook this up. Now, of course, we could do this sequentially, but we're gonna let level kind of handle it for us. Alright, so now that we have that, inside this created, it's going to take a closure. Now the nice thing with this closure is that it will actually give us the created model. So we can accept that as user. And then we could do whatever we need to do to make that happen. So of course, as we've learned before, the easiest way of creating a profile is through the relationship. That way, the user ID gets set up for us and everything else. so we can simply say user profile, create. And really, that's it because if you recall, everything in there is nullable. Except for the user ID. However, maybe we should just make some defaults. So for title, let's go ahead and maybe just use their username, let's just say title will be the user username. That way, at least a user will have one little thing in their profile, and it won't all be blank. So the title will just be the username as a default. Alright, so let's give this a go one more time, and see how it goes. As a matter of fact, we'll go ahead and completely kill the database. And then let's create our new user. Alright, let's go back here and go to the home. Let's go ahead and register a user again. So test user test, username, test, password, register. And let's check this out. Let's go to profile now slash one. And sure enough, this user now has a profile. And notice that the title is test. And of course, we can edit that and say Free Code Graham, very cool description, URL freako camp. And now all of this has kind of led to us being able to have a profile image because remember, that was the actual reason why we needed to refresh our database. So let's go ahead and add that image there. Hit Save profile. And yes, it did work. However, we still have that hard coded image in our profile view. So let's take a look at that. Now. Let's go to the profile slash index. And this image right here, we can now replace that with a user profile image. And of course, we still need to go into slash storage, slash whatever the profile image is back to Chrome refresh. There we go. So that image is being pulled up. Now, of course, we do need to give it just a class of W 100. To fix that, with issue, and there we go. So now if we wanted to change our image, let's give it a new image, let's say this image right here, save profile, but we have a new profile image. So our profile image is working, just like that. Very simple. very clean, very cool. So there we are. So now of course, we could still add a new post, my first post, choose file, post image, add new posts, and there's my post. And if I click on it, now we have the description and everything in here. And now actually, that reminds me remember that in the actual Instagram, check this out, they are using that image, and I said, Well, we're gonna have to put that off. Because we're not ready. We don't have that image yet. But now we do. So let's take care of that right now make this look a little bit more like the Instagram one. Cool. So let's go into the show view. And where we have this h3 right now, I'm going to replace all of this actually. And so let's do a div. And inside that div, the first one is going to be an image. So of course, the source of the image, we kind of know. But we do need to grab it slightly different because what we actually have in this view, is a post. So let's do something, let's grab the post, then grab the user, then grab their profile. And then we can grab their image. Notice how important it is to have all of these relationships. So we have a post, we grab the user, and then we grab the user's profile. And then finally, we can grab their image. So let's add slash storage, slash and then that. And let's add a class of with a 100. Let's go back here. There we go. So we're getting that now let's just make that rounded. That's going to be a class of rounded circle. Nice. There we go. All right, what else do we need on that? Well, we need the username. So let's create another div in here, and maybe have that under an H five. And let's say, give me the post, grab the user and give me their username. What does that look like? There we go. But now of course, we need that to be kind of in line with each other. So let's change the display of this to display a flex. Sure enough, that's working. Now this image is huge. So we're going to have to control this width a little bit. Let's put an inline style here of max width of maybe 25 pixels. Let's see what that looks like. Yep, too small. All right, let's go to 50. I think that's closer. Yep, that's just about the right size. So now we do need to line this up correctly, because this is way too high, we needed to be in the middle. So display a flex. And let's go ahead and give it a line items, center. And that should fix it for us. There we go. Alright, so now let's add a little bit of padding to the right of the image. So let's say class, padding, right, maybe three. Yeah, that's looking good. So we have that. And it looks like it should be bold, and maybe slightly smaller. So maybe let's just put a paragraph tag here. And let's give it a class of font bold, first font weight bold. And let's see what that looks like. Looks like we have a little bit of padding there. Because of the p tag. Notice here how tests bump up too high. And there's a reason for that is actually there is some padding built into the paragraph. So if we just change this to a div instead, there we go. See that fixes that looks to be a little too big, the image nice seems to be a little too big. So let's go ahead and make that image slightly smaller. Let's go to 40. There we go, that's looking better, then it looks like there's going to be some sort of HR horizontal rule. Right? Notice here might be a little faint, but there is a horizontal rule there. And then it's off by a little bit because it actually starts with the username and bold followed by whatever the description is. So let's check that out. So it's not caption, but rather it's really this. Let me just copy this just for now. I'm going to put it in here. And instead of a div, let's make that a span. And that should give us what we need. There we go. Now test and test. Both of these should be clickable, these are actual links. So when we do that, it's actually going to mess up our color a little bit. So we're going to have to go back in and change that. So let me grab this and we need an anchor tag and it's going to To go to slash profile slash, and the profile ID. So let's say post user ID. Okay, and then we can paste that back in. So now if we click on that now, it does take us to our profile both of them do. But like I said, it messed up our color a little bit. So let's copy that. And let's wrap that in another span, and then click class. And let's just say here, text dark. There we go. So now we have our text, dark back, great, little bit of bootstrap stuff there, nothing crazy. Let me go ahead and add this up into new lines, so it's easier to see. And actually, it looks like it forgot to put span back here. So let's fix that as well. Great. And let's do the same thing on this one. So we'll have that then we'll have our anchor tag, then we'll have our text. And it looks like it did the same thing here. So span again, anchor tag, and then finally, we will have the caption and then we'll wrap up with the ending of a paragraph. Alright, so that's looking much, much better in terms of what it's supposed to actually look like from our example here. Now, one final thing you do see here is a follow now we're going to add that functionality. For now let's just go ahead and add the button. So let's add the button right after this one. Let's just see what it looks like. It's not going to go anywhere right now. But let's just say follow. And of course, we are going to have to give it a little bit of padding, it's gonna butt up right on. Now is it follow? Yep, it is follow it's looks like it's slightly smaller. But that's okay. Let's give it a little bit of padding to the right class, padding, actually, to the left padding left three, which should match the padding right of three that we gave the image. And there we go. It does have a small character somewhere in there. Maybe we could use a pipe. net, we'll just keep it simple. They are using some sort of SVG image here, right in between the separator. But again, we're not too concerned with that. So that's what we get. So that might be too much still. But if you click follow, obviously, it's going to follow that user. Alright, so this is looking great. So what else do we need to fix here? Alright, so let's go back here. And let's take a look at this profile. Is everything done here? Yep, for the most part, everything in here is done. So we are able to register users add new posts, I'm gonna go ahead and create another user, just so that we can see what that would look like, we'll say new user to another email, Free Code grandma on this one, we'll set our password we'll set a password. All right, it's still going here, we do need to fix that at some point. But anyway, here you go. So this is our profile. And then now, this is our regular profile. So it does bring me to a good point here. So this image, of course, when the user first creates the profile, there is no image at all. So we kind of do need to have just a coming soon style photo, let me go ahead and grab one now. So let's edit this profile here. And let me give it that new image. And behind the scenes, I did grab a no image available, nothing crazy, nothing fancy. Let me go ahead and run this through here. Let's add a description. And let's add a link, let me grab this image that I grabbed from behind the scenes. Alright, so no image available, this is going to be our default image and just wanted to run it through there so that it is somewhere inside of our system. So let's copy image address right now. And let's go back here. And up here, right where we show the profile image. This is the type of thing where it would be nice if we could intercept this call, what I want to do is the following, I'm gonna make a special method in my profile model to be able to always just return an image, whether it's the real image or the temporary image. So check this out. Let's go to my profile model. Alright, so let's go ahead and add a new public function profile image. And this is what we're going to call every time that we need that profile image. So this needs to return either the default or the image that was actually provided by the user. So how can we check that? Well, we could say, this image, remember, this is the model so we can access any of their properties by just calling this image. So if this image is set, then we're going to return slash storage slash and then this image. Otherwise, let's return that default image that we uploaded. And all we need is just this part. So this is going to be the default image that we're going to have. Now we do have a little bit of repetition here with the storage. So perhaps what we can do is actually pulled this outside right here. So we're going to return slash storage slash. And then it's either going to be our profile image, or it's going to be this image right here. So let's go back to the view and change that. So from here, now, we don't need to add this storage anymore, we can say post user profile. And then we can call profile image that does need parentheses because that's obviously a method. Okay, so now let's go to our index, and I need to make the exact same change. So right here, where we are grabbing the profile image, go ahead and say profile image. And we no longer need to add the storage. So everything should be working exactly the same. Now it looks like this is broken here, our image is not showing up. Let's see what happens. Let's go back to PHP store. I must have made a mistake here. Let me die and dump this right here just to see what we are actually getting back from our function. So it looks like it's getting back slash profile, slash that it doesn't look like it's grabbing storage. All right, let's see what's going on here, back here. So we are returning that. And it looks like it doesn't like the way that we wrote this. So simple fix for this would be if we just grabbed this. And let's just say, let's move this to a variable instead. So we'll say storage slash image path. And then up here, we could say, image path equals that. I think that'll fix it. Yep. And it does. Alright, so let me go ahead and take off the Diane dump from here. All right, so take that off, take the parentheses off. And there we go. Now, let's go into the other profile. So we can click into one of these, and that is still working correctly. So now when a user creates a new account, they do have just a regular image. Let me make another one, say test to test calm. Cool. Let's put a password register. Now let's go to their profile. Three, there we go. So no image available. So that's pretty cool. That is a nice default that we have. So if they click Edit Profile, of course, they can do that. Now, in the process of doing this, we did break something, and I'll show you what it is. So let's say that I don't want to put an image, right. Let's put a valid URL. When I click this, now we have this undefined variable image path. So why is this happening? Well, let's take a look at the code snippet that we got right here. So we are always assuming that there's going to be this image path, but the image path may not be set. And if it's not set, it just means that there was no image in the request. However, down here, we are always assuming that image path is set. So let's fix that. Obviously, the problem is right here. Now I can't say something like just say no, because then whenever there is an image and no new image is passed, then we are essentially deleting the profile image. So we definitely don't want to do that. What I'm thinking is something like so let's actually extract this to a variable. And let's call this variable image array. So this image array variable is going to be actually set up here. So once we save our image, we'll set image array equal to the array that we need to save the data. Now, if image array is not set, in that case, let's go ahead and just default to an empty array. So an empty array will not override anything in our data. So we're setting this image array is going to contain the image. But this is only happening if there is an image in the request. Otherwise, the only thing we're going to pass into this array merge is going to be an empty array, because obviously at that point, this is not set. Alright, let's give all of that ago and see what happens. So there is no profile image selected right now, I'm just going to save profile that works. This choose an image now let's choose the coders tape logo. That works. But now if we edit our profile, I said cool 234 no images selected. Yep, we still have our coders tape profile. So that's a nice little fix for that sequence that we actually broke. So now that's working, and we're good to go. I am obviously signed in as this user. So we can edit profile, we can add posts. If we go to a different profile, say two, then of course all of that goes away. We've worked on this quite a bit. We are making fantastic progress on this. Up next, I do want to handle the followers. That's kind of the next thing on Instagram. When you have a couple of different users then of course we want the ability to follow them. Now if you remember back Here, there is a follow button in our show view. And there should also be a follow button in our actual profile. So here it is, here's that follow button. And we don't have one right now. So let's start with the UI. Let's go into that index view. And right after the username, I want to add a button. So let's add a button. And it's gonna be follow. That's what the buttons gonna say, not bottom, but button. There we go. So a button of class button. And button primary. Let's see what that looks like. Okay, it's all the way on the right now it's probably okay. But if we did want it to be there, then we're gonna have to actually put this inside its own div. Because right now, this box right here, this whole section actually has a display of flex. So it's going to default to the right. So there we go. So now, if we give it a display of flex on this box, now that button is there, just need to give it a little bit of margin. So maybe margin margin left four. There we go. Now the button does look weird. It's because it's got an h1 on it, a couple of different things we can do here, we can either change this to a div with a class of h4. I think that'll fix it. Yeah, it does. But it does make this quite smaller, which is probably okay. Let's also align items center. There we go. So that moves that down. And let's add a little bit of padding bottom to this whole thing. There we go. All right, you know what, that's actually looking much, much better. I think this text size is more correct, we what it should be. So now this Follow button, we need to make this button actually do something. So what I want to do is, when you click that button, we don't want to restart the entire browser. So we're going to bring in an entirely new concept for this button. And that is the concept of view, we haven't touched a lot on the front end. So this is going to be a cool and different approach that we're going to take for this. So we're going to convert this Follow button into a view component. And the reason again, why I want to turn this into a view component is because this should not require you to refresh the entire page. But rather, when you click on it, I just want to talk to the server and say, Hey, follow that profile. And then we're going to get some feedback. And then if you click on it, again, is basically going to toggle that and say on follow that person. So it's going to be fairly simple to do with view. So let's jump right to it. Let me close all the windows up. And now let's explore here a little bit. We talked about our front end right at the very beginning, but we didn't do much with it. So right now we looked at resources, JavaScript components, level ships with this example, component dot view. Now this course, of course, we are covering Laravel. So we're not going to cover a ton of view. But I do want to get your feet wet on view. In general, this example component is a working component already. And it is registered in our app dot j s. If you scroll down here, we see here how view has a component called example component. And that is under the example component dot view. Alright, let's rename this component right now. So let's do refactor, rename, and we're going to name it follow button. And then the Follow button dot view. Let's refactor that. And then let's change this to follow button and rename our file to follow button dot view. Okay, so now inside our Follow button, what is going to go in here? Well, most important thing to remember about view is that everything needs to be wrapped in this diff, you cannot have something like this, you cannot have two divs, because then it will tell you something about how there is no root div. So you need to start with a single tag, nothing outside of this, everything needs to be wrapped in that tag. Let's go back to that index blade and grab our button. And here it is. I'm gonna cut this out. And I'm going to paste that right in here. And then in there, let's have a follow button. And that's it. So that is going to refer to our actual component. So check this out. So we moved the button in here. Now of course, we do need to run NPM run, Dev. Now, Dev is what we would use if we want it to run just one time. However, if we run NPM, run, watch, what it will actually do is continue to watch all of our files. And whenever there's a change, it would automatically compile all of our code again, and present it to us in the browser. So that's really what you would use during development. You want it to continue to run In the background over and over, and over and over, just watching for changes that you make. So all right, so let's wait for this to finish really quick. And then we can check it out on the browser. All right, so it's done. Let's go back to Chrome. Let's hit refresh. And we don't see a difference at all. Obviously, we're still getting our button. But this time, that button is actually inside our view component, check this out. Follow me now I'm gonna change that. notice up here, as soon as I hit safe, notice the little pop up, there it is. So level mix, compiled, go back, refresh. And there it is. Follow me now, how cool is that. So while you're running the NPM, run, watch, every time you save a file, it will automatically compile those assets for you, and present them to you on the browser. So the first thing that I want to do with this button is that whenever I click on it, then of course, I do want to create some sort of action. So basically, we need to be watching for a click on this button. And whenever that click happens, we need to reach out into our server and do something right create that connection between two users. So how exactly do we do that? Well, in view, it's quite simple. Let's just say add, click. So whenever a click happens, let's go ahead and say, follow user. So follow user will actually be a method. So let's add a method here. methods. And inside methods, we're going to have this follow user method. Right? And let's just for now, let's just alert inside, just so that we can see that that is working. Let me hit refresh. Click that. And sure enough, we are inside see we're hitting that method. All right, that's pretty good. So this follow user needs to reach into our server. How do we reach into our server? Well check this out. Laravel actually ships with axios installed. And axios is a cool library that allows you to make API calls extremely easy. So there it is, window, dot axios. All this comes set up for you out of the box, I'm just showing you so you have an idea of what you're actually getting in the full package. But truthfully, you could just use it and trust that Laravel has it in there for you. So where do we need to reach into? So this will look something like axios? Make a POST request to what endpoints are we going to hit? Let's check out the web dot php file. And let's add a new post route to match that new axios call. So we'll say post, and what are we going to post to how about this follow, and then maybe the user, that way, we can actually have the user that we need. So obviously, we're gonna have to pass this through that. Now for now, just to show you how it's going to work. Let's go ahead and just return maybe an array that just says success, I just want to get it to the point where it actually works. So let's check this out. Let's hit the slash follow, slash. And for now, I'm just going to hard code one. Obviously, we don't have that just yet. Now if we get a success, then we can go ahead and grab our response. And then let's just alert the response. Great. Let's go ahead and hit save. And let's head back to the browser, Chrome, hit refresh. And I'm going to hit the follow. And of course, we do get an object. So that's great, we are getting a response. Let's just go ahead and get response data. And I believe that that's going to have our success message. And sure enough, there it is. So we are hitting the server, and it's responding back with the proper response that we need. Alright, so now that we hitting that, of course, we're not going to have this closure base route, but rather we're going to need a controller. So let's make one now I'm going to open a new tab. And then let me head back into the same directory. There we go. Alright, so here, let's run php artisan make controller. What is the controller going to be called? Maybe just followers controller or follows controller maybe follows controller? We'll we'll settle on follows controller. All right, back to PHP storm. And now what kind of Route should we have in follows controller? Meaning what should the verb BE? Well, I see this as being a store because we are basically storing a following. We'll just use the store action on that. And so back in our web routes, all we have to do here is pass in follows controller at store. Alright, so that's going to hit our controller. And in our controller, we are actually going to accept the user as we have before, because remember, we are passing in the user. Now currently, in my view, I am hardcoding one and that is obviously not correct. So how could we get the user ID? Well, the easiest way to do that would actually be to just pass it through, we could just give it through Follow button. And in view, we can have any number of additional data fields. So we can pass in, or they're called props, right as in properties, that's what they're called in view. So let's give in the user ID by just calling user ID. And in view, we just need to accept that as a prop. So let's set that up. Now, let's say props. It's going to be an array, and the only one we're going to have is user ID. Alright, so now instead of one, let's actually pass in the user ID. So this user ID, and just to make sure that we did get the user correctly, let's return maybe the user's username. That way, we know we're actually getting the correct value back. Alright, let's head back here. Hit refresh, hit follow. And there it is. Test is obviously the username of this profile. Let's visit a different profile. Let's go to to hit that. There we go. Free Code gram. So we are successfully fetching the correct user. Okay, so now that we're all set up, how do we actually connect a profile to users, what we're going to explore is a many to many relationship. Up until this point, we talked about a one to one relationship, we talked about one to many, and now a many to many, because a profile can have many followers, in a user can follow many profiles. So it's a many to many relationship. So how do we handle in many to many relationship, obviously, in the previous two examples of relationships, we added a foreign key to one of the tables, and that worked out. But in the case of a many to many, we actually need to create a pivot table. And a pivot table is simply a table that holds the ID of the two related models, it's fairly easy to set up. But there is a naming convention. So let's talk about that. Now, up until this point, really, every time we run php artisan make model, we are creating a model. But we don't need a model for this one, we actually just need the migration. So we do have this make migration command instead. And if we run php artisan help make migration, then we see that of course, the name is required, as always, but we do have this create flag, that way we can pass in the table that is going to be created. So php artisan, make migration. And obviously, with a lot of Laravel stuff, there's going to be some sort of naming convention. So let's take a look at what are the two models that we're going to connect? Well, we're going to connect a user and we're going to connect a profile, those are my model names. So in level, the first thing we need to do is put them in alphabetical order. So we'll actually be profile and then user, they will make everything lowercase. And then we'll put an underscore in between. So that's going to be my table name, profile underscore user. So let's go ahead and run create on that. And let's name our migration. Something like creates profile, user pivot table. Great. So that migration is created for us. Let's go back to PHP storm. And let's check that out. Now, this is actually fairly simple to set up because it really only needs two fields. So we'll say unsigned, big integer for the profile ID. And we need another one for the user ID. And that's it. That's all we need on this table. Let's go ahead and migrate our database. php, artisan, migrate. And there we go. So now we have that profile users pivot table. Let's set up our relationships. Let's start with the user model. So our user model has posts and it has profiles. And now it's going to have maybe following that's what I'm thinking, I'm going to call the method because a user is going to be following a profile. So let's go ahead and call it following. And how do we return this? Well, we need to return this it belongs to many, and what does it belong to many profile AP class. And that's it. That is set up for us. Now let's do the same thing on the profile. So what should we call it on the profile? How about we call it followers. So, I profile is going to have many followers return this belongs to many user class. So it belongs to many users. Remember, a profile can have many users that follow it. So they are the profiles followers, and then our user can follow Hello, many profiles, so it is following many profiles. So we've basically set this up so that it reads nicely. The nice thing with this is that we can label to actually make sense. So that's great. Alright, so we have all of that setup. So what do we actually need to do in this follows controller? Well, we need to go ahead and grab the authenticated user. And then we need to basically attach or detach this relationship. Now there is a nice method that Laravel provides for us, which is toggles and toggle actually toggles between connected or not connected, which is perfect for us. When we hit the Follow button, of course, we want to follow them. But then if we click the same button, again, we want to unfollow that profile. So let's do this. Let's return the authenticated users. And then let's go ahead and fetch that following relationship and call the toggle method on it. So what are we toggling? Well, we're toggling not the user, but we're actually toggling the user's profile. Remember, the user that we're referring to is the user that is being passed into us, not our authenticated user. Now we are using our authenticated user to actually do the connection, but then what we're going to connect is the profile. And actually, it should not have parentheses. So it should be attaching to the profile. Alright, let's give this a go. This is returning. So we should be able to get whatever that is back in the browser. So let's go to Chrome, hit refresh. And I'm going to hit the button. And now we get an error. Let's see what we got. We got a 500 error. Okay, let's check out what's going on here. Preview, it says call to a member function following on No. Alright, so that is interesting. What is happening here is that I'm actually not logged in right now. If you notice here, we are not actually getting the correct functionality. Because we're not logged in, we're going to handle that a little bit differently. But let me go ahead and log in. And I think we're going to get exactly what we need. Login. Let's go ahead and go back to that profile. And now let's hit that follow button. And there we go. So we got an object back. And I bet you that object has got the information that we need. So let me just go ahead. And perhaps instead of alerting that, let's console, log, the response console, log, the response. Go back here, hit refresh. Alright, so there we go. We're getting a JSON array with attached and detached. So basically, what's happening is that whenever we attach something, the associated model is going to be under attached. And then whenever we detach the associated model, it's going to be in there. So if we open up detached, of course, we see that it's ID of one. So let's see if we actually created that connection. Let's go back here and do some exploring in Tinker. Let's say let's grab the user. So we'll say user, find one. And now the user, give me everybody that you are following. And that's not returning anything. I think it's because I click this button twice. Let me go ahead and hit the button again. And let's try that one more time. Let's grab a fresh copy. Whoops. There we go. So with a fresh copy, we do see that we have associated using that pivot, and we see that user ID one is now following profile ID of one. All right, if we unfollow them, then of course, when we head back here, let's grab that user one more time, user. Fine, Id of one. user, give me everybody that you are following. Nope, we're back to empty. So that's working just fine. However, we're not giving any feedback at all to the user. See right now, basically, whether we click this button or not, we have no idea on what the actual status is. So we need to somehow have that in here. So let's do something. Let's just set a quick data attribute here. And let's add it right after mounted. And let's say data. Data is going to be a function that returns an object. Let's use the keyword status. So first and foremost, status needs a default state, whether the user is initially attached or not to that particular profile. So how are we going to get that initial state, we're going to have to somehow pass it in in this Follow button. Maybe we'll just say follows as in this particular user follows that. And then we're going to have to basically have some sort of variable passed in from our profiles controller. So let's go to the profiles controller Right here in the index, we're going to need to somehow figure out how to determine if that user follows this profile, right? So that we can pass it through to our view. So let's actually attach follows. And how do we figure this out? How about this? If the user is authenticated, right, so we are authenticated, because it may be the case where we are not authenticated. But if the user is authenticated, then let's grab the authenticated user following. So let's just say is the authenticated user following contains user, meaning is the authenticated users followings. Does that contain the user that got passed in? Alright? Otherwise, let's just return false. As in it's not following right now. All right, let me just do a quick die and dump on this just to check our logic. Let's go back here. Hit refresh. Alright, so we're getting false. Let's see why that is. Let me do a quick toggle on that. And let's see if we can get a different response. It says undefined variable follows. All right, what's going on here? Yeah, of course, I mistyped this, this should just be a string. Here we go. Alright, so let's check if it contains not the user. But if it contains the user ID. All right. Let's try that. And there we go. We're getting true. Great. So now we can actually just pass that through into our view. So status, we're actually going to set that default to follows will be this that follows. And we need to accept that as a prop. So follows. There we go. So now let's see what we get. Let's hit refresh. Sure enough, we are back to this. So now what we need to do is the following, we need to toggle what this is from follows to unfollow. So let's go ahead and bind that using v text. And let's have a computer property, maybe for button text. And let's get rid of follow. And so let's create a new computer property, computer. button text. So here, we're just going to return whether or not this status so this that status, if this status equals true, it means that this user follows. So we're going to go ahead and say, on follow, that's what the text will be. Otherwise, it should be follow the same as what we have now. Hit refresh. And sure enough, so now it says unfollow. And if we click on it, obviously, it doesn't change right now. But if we refresh, now it says follow. So that is working, we are properly showing that is just that we are not updating the UI. So let's do that now. So let's say this, when we receive a successful response, then I want to change status. So we need to say this dot status equals and what does it equal, all we need to do is flip the status, because we're getting an initial status, like so all we can do is just maybe just toggle this that status. And I think that that'll actually work just fine. Let's go back here. Hit refresh. Alright, so let's hit follow. On Follow, follow, on follow. So we're able to attach and detach without a problem. So notice this last one, of course, in the attach section, it does equal to one, if we hit that button again, now it's zero, and this one is one. So we are successfully following this particular profile. How cool is that? So now let's tackle that error when we are logged out, we should not be able to follow somebody. And if we hit this button, right now, of course, we get an error, we get a 500 internal server error. And really, we should be getting an authenticated, what is actually happening, is that following is no, that's kind of cryptic. Let's see what's going on. If we go back here to follows controller, we're getting this authenticated user following. So this is where it's giving us the error. Because this is actually know at this point, if the authenticated user is no, then really, it should not even be touching this. So how do we fix this? Well, if you remember, we can attach a constructor. And to this constructor, we can say well, this needs a middleware of off. And I think that that will change our air. Let's check this out. I'm gonna hit refresh. I'm going to hit follow. And sure enough, now we get a 401 on authorized. Alright, so now that is actually going to hit a catch block. So let's say catch any errors. And now we need to do something different with those. So if we get any errors, what should we do here? Well, we can handle this several different ways, but I think probably the best thing we could do is just redirect the customer back to the login page saying, Hey, you know what you are not logged in, go ahead and log in and maybe try that action again. So if we catch an error, and if that error is of the correct type, because we may get a 500, that's totally different. But we are looking for this 401 on authorized. So if we get errors, dot data, dot status is equal to 401. In that case, let me go ahead and just window dot location equal to slash login. And I think that's all we need to do. That will basically send our user into the login page. Alright, let's see if that will work. Set refresh. Alright, so we're getting a property status is undefined. I must have made a mistake here. errors that I'm sorry, errors dot response. dot status. There we go. That should work. Hit refresh, hit that button. And there we are. So we are sending them to the login page. But if we are logged in, let's login. Now when we go to that profile, we can hit follow. Let's go to a different profile. Here, follow on that one. So now we are following two people were following that one. And of course, we are following the first one. So what is the next step? Well, now that we have this follow functionality, of course, we need to be able to get a count on the followings of that particular user. All right, let's check that out. Back to PHP storm. Let me close everything out. And let's just go back to that index blade method. Alright, so we are looking for the where it says 23k. So we're going to replace that with the dynamic and let's just say, user profile followers. And let's get the count for that. Alright, does that work? Yeah, you got one follower. And if we click that button, obviously, it does not refresh. But if we refresh the page, we're back to zero. So we're going to follow that person. Let's go ahead and hit refresh. And now that does update, of course, we can run through some special JavaScript stuff to be able to update that. But that is beyond the scope of this course, as this is really a level course not really a JavaScript course. So if we had another user, let me go ahead and log out, and maybe log in as my other user, say, test two. Now, let's go to that same profile. And we see that he has one follower, let's give them another follower. Hit refresh. So now this person has two followers. How awesome is that? So we are having that functionality doing just great. So now, we can also fix this following, because what we need to do is figure out how many people they follow. Alright, let's see if we can fix that one. Let's go back here. And instead of 212, let's say user following. And let's get the count for that. Let's go back, hit refresh. And we see that person is following two people. I'm actually logged in as the third user. So there we go. We are following two people. Let me unfollow somebody on follow. And let's go back to the profile. And we're back to one. And we don't have any followers and no posts. So all of that is working. How great is that? We're making fantastic progress on this. Let's keep plucking through this. So up until now, I've kind of held back on you in terms of what utilities are available from Laravel. I just did not want to introduce so much upfront. However, there's a very important tool that we need to talk about. Let's look for it in the documentation Laravel telescope. So telescope is going to give you an inside look into your application. Now it is very easy to pull in. And it does have a very nice UI that you can use for development. So to install it, we need to do it composer require and then we need to install it using this php artisan command. So let's go ahead and do that now composer require Laravel slash telescope. And there we go. So if we run php artisan, we now have a couple of new commands at our disposal. And it's right here, the telescope section. So let's run that telescope install. And there we go. So everything's there. And finally, we need to run php artisan migrate. And that adds a telescope entries. Alright, so let's head back to our project. And now what we could do is we can visit slash telescope. And there it is. This is level telescope. Now I'm gonna give you a very quick overview of it, but definitely spend some time looking around to see what it can do. So Laravel telescope tracks your application. And it will record any activity that comes in, whether through requests, or through models or events or commands. I mean, it covers the entire thing. So if we looked in the command section, for example, we see that we just ran a migrate command 30 seconds ago. Let's run another command. For example, let's just run php artisan. Okay, now let's go back telescope. And we have now this load new entries. And we hit that, we see that we'd ran the list command, six seconds ago, scheduled jobs, if you have any of those, those will show up here. exceptions. For example, if your application crashes, it'll show up here. We have logs, dumps queries, for example, this is an important one, this will track any of your queries. Let's, for example, let's load up one of our profiles, let's say profile one, I load that in a new tab. And so we see we have new entries here to load. And there we go. These are all the queries that ran behind the scenes, you can actually click on the little eye right here, and view the full query, everything that ran and you can even view the requests. So we requested a web route of slash profile slash one, we got a status code of 200. You can see the headers, the session, that response. This is unbelievably powerful for any development environment. What else can we see here? How about models, you can have your models they'll show up here, events will also show up their mail, we're gonna start talking about how to send email. So this is an important one, notifications, gates cache, we're also going to talk about cash. And finally, Redis. So a very complete toolset that hooks up right into your application, and keeps track of everything that you need. So this is pretty cool. What I want to handle next is I want to handle this status right now. So if we log in right now, this login, we've been going to this slash home. And that's a dead route right now. So we really do need to do something about this. And what I'm thinking is we can get rid of this slash home altogether. And perhaps, if we go to just a regular domain, I want to see the latest posts from all of the people that I am following. in sequential order. That is basically how Instagram works. So let's change one thing at a time. First off, we need to change where we are redirected after a successful login. So let's go into PHP storm. And let's dig through app HTTP controllers off. And let's look into login controller. So right now we see that we are redirected to slash home. Let's just change that to slash. And let's try that one more time. Let me go ahead and log out. And there we are. Alright, let me log in again. And hopefully this time, we'll go to the right place. And there we go. Alright, so now we are redirecting here. Now, we still have this link here for home. But we're gonna get rid of all of that anyway. So I'm not too concerned about it. Now, my routes file, I do need to clean up this route. Because right now, it is just returning a welcome view, which we're going to get rid of altogether. So what am I thinking here? Well, we actually don't even need a new controller, because what I'm thinking is I'm going to reuse my posts controller, and we're going to call the index method on the index method is the one that kind of shows all of the resources. So it would just make sense to call that. So let's move this down so that it joins all the other routes. And let's say post controller at index. Obviously, that doesn't exist just yet. So let's go ahead and create that post controller. And right up here at the top, let's go ahead and create a new public function for index. Now notice that this entire controller is under the middleware of auth. So whenever we hit here, we are going to have an authenticated user. So what we need to do is we need to get all of the posts of all the people that we are following, and put that in reverse chronological order. Now at first glance, that may seem simple, but it does take a little bit of thinking to get through to this. And the reason is that we are following profiles, right. That's how we connect our user to the people that we are following. However, all the posts are actually associated to users not to profile. So check this out. Let's go to the Create posts table. And let's check out what we have here. So we have a user ID not a profile ID. So how do we grab that? Well, here's what I'm thinking. Let's grab all of the users. First, I want to grab all of the users that we are following. So let's say authenticated user, everybody that you are following. I only want their user ID. And we can use the pluck method for that. So let's go ahead and pluck all of the user IDs. Go ahead and done users. Just to show you what we get there. Go back to Chrome And if we hit refresh, you're going to get this error. And what this error is basically saying is that there are several user underscore IDs. And it just doesn't know which one to use. It is an ambiguous column name. So which user ID are we talking about? Well, we're talking about the user ID that's in the profiles table. So we said profiles dot user ID, that'll probably fix it. Let's find out. Refresh, there we go. So now we have a collection of user IDs. So we're currently following user ID one, and user ID three. So now we have a collection of users that the authenticated user is currently following. So with that, we can probably fetch all of the posts, like so let's say posts, equals, we can reach into the posts. And we do need to import that up here at the top. So that's use App post. So we could say were in meaning we're gonna pass it an array of data. So where the user ID is in that list of users that we just grabbed, and go ahead and get me everything for now. All right, let's go ahead and die and dump that instead, posts, refresh. So now we get a collection. And it's got two items in it. And what we have is two posts inside of it. Well, that's great. But it's in reverse order. Because right now, obviously, post ID one was created them for 28. Let's check out the next one. This one was created for 29. So this one should be bumped at the top. So we need to reverse the order. So we could do this in several ways. We could either say, go ahead and order by created Add Column in descending order. And if we hit refresh, now, we should have post ID of two at the top. And we do now this is such a common thing that actually is a latest method that we can call, which will do exactly the same thing. But it's a little bit shorter, a little bit easier to read. And refresh, we should have the exact same result. And we do we still have ID of two. Great. So now we do have all of the posts that we need. So now we need to return a view. And what is the view going to be called? Well, this is the posts controller, and this is the index method. So not much to think their posts dot index. And we do need to pass through the posts. Alright, so now of course, that view doesn't exist. So let's go ahead and create it. If we copy the save the show that blade that PHP, let me save this as and rename it to index. All right. So let's see here, what's the fastest way we can get this working? I'll tell you what, let's grab all of this. And let's wrap all this in a for each. So for each posts as post, go ahead and do that. And for each. Alright, let's check that out in the browser. Okay, so that works, right, we are able to see all of our posts in order. So now we need to work on our view a little bit, because obviously, that's probably not how we want to see this. So here's what I'm thinking the image at the top and then at the bottom, we'll put the caption. So let's do something, let's do a column of eight. But then let's offset by two. Let's do offset two. And then let's end that row. And let's start a new row here. So div with a class of row. And that should begin to get us where we need to be. Let's see what that looks like. So there we go. So now we have the image at the top. But really, all we need is just this bottom section right here, everything after the H r. So let's delete everything on top of the horizontal rule. And including the horizontal rule. Hit refresh. Okay, so that's looking good. So now we need to give this the same treatment, let's give it a column of eight, but with an offset of two. All right, so that's working good. So we're getting that underneath. Let's add a little bit of padding, let's say padding, top and bottom of four. Let's see what that looks like. When we probably need the top to have a little bit less, so let's say padding top of two, padding bottom of four. Let's keep it like that. And there we go. I like that. Okay, so that's looking pretty good, we could still go to the profile. If we clicked on the image, though, we should probably be able to go to the profile as well. So let's change that. Let's wrap this image in an anchor tag. And where's it going to go? Well, it's going to go to slash profile slash Post, user ID. And let's put our image back in. Refresh. So now that image is clickable. Great. So that's pretty cool, we're able to see that. So that's pretty easy, right? Getting all these posts to show up on this homepage. Now the image is a little large. So maybe let's do something instead of call eight offset to make them all slightly smaller, let's say offset of four. And let's drop this to four. So too small. Yeah, that's probably too small. All right, let's do two column of six. And let's do an offset of three. There we go. That's a good size. This is probably more like the Instagram size. Anyway. So that's working great. So what's up next? Well, behind the scenes, let me add a bunch of different posts, so that we can start some pagination stuff. All right, I'll be right back. All right, and we are back. So what I've done is behind the scenes, I just copied that post, over and over and over and over. The only reason for that is I just want to show you how easy it is to do pagination. So I'm thinking just for this example, let's show the first five posts only. So we're going to paginate by five. Now, if you're not familiar with pagination, it just simply means that instead of showing hundreds or unlimited amounts of posts, we just want to limit it to the first five, then you can click next and get the next five, and so on, and so forth. Now, traditionally, this has been kind of a difficult task. But Laravel makes this almost a no brainer, check this out. Let's go back to PHP storm. And in our post controller, instead of using get, we're going to use paginate. And then inside of here, we have to pass the number of records that we want per page, like I said, in our case, is going to be five. And now if we hit save, and we head back, and I hit refresh, we got 1234 and five, and that's it, the page ends. So all we need here at the bottom would be that little next button. So how do we add that let's go back to the index. And then right after the for each, let's add another row with a column of 12. And in here, let's simply echo out posts, links. So this special links gets added whenever we call the pagination in the controller, when we use paginate, as opposed to get that is when that happened. So that's how that gets added into it. Because that, there we go. So that's how that gets added into posts. Let's go ahead and hit refresh. And now here we go. So we can click page two. And here are my other posts, page three. And here we go. Now I want to center this right underneath on the page. So that's simple enough, let's just do a display of flex, and then just say justify center, justify content center. And there we go. So that's it, we have pagination level really does make this a complete no brainer. It's so easy to do. It's almost laughable. So now we are showing five at a time. How cool is that? One thing I do want to touch up on is this. If we go back here to telescope, you see this right here, it is basically the exact same query over and over. But with a limit of one. This is what is known as an N plus one problem. And what's actually happening is that when we load this page, let me show you, when we load this page, we are fetching the user relationship, but we are not loading the user relationship. So every time that it runs through the for each statement, it goes into this section here and it loads the user, but one at a time. And that's why we see that limit of one. But there's a much more efficient way that Laravel can do this. So let's go ahead and fix it. So all we need to say is, alright, when you are loading all of this, I want you to load it with the user. And the user. This keyword right here is talking about the relationship. So if we go to our post model, this right here, says user, that is where we're going to be loading. Let me hit refresh, back to telescope. But now this time, we have a single query. So now we got rid of all of that limit. One problem. Now one thing about telescope is that after you've been running this for a while, it does get a little cluttered. So let me show you how to clear it up. We look down here there's this telescope clear. So we can run that command whenever we want to just erase everything and start over. So that gets cleared and if we go back here, there we go. So we are back to fresh now. I'm going to refresh this page. And we're going to see how many queries we're actually running. So that's working out pretty good. See, and this is the type of thing that Laravel telescope makes really easy to see. So what else can we do? All right, there's a couple of things I want to touch up on. So if we go to our profile, this section right here, right now, we are fetching that every single time the user loads in, but I want to make use of Laravel caching. Because caching and Laravel is so simple, that it's almost really just a no brainer to use it. So right now, instead of every time I load the page, we go ahead and calculate each one of these fields. For my application, in my case, I'm determining that 30 seconds is perfectly fine, which means that all of the requests that come in within 30 seconds are going to be delivered a cached version of that number, as opposed to the real number. So it's gonna take a little bit of refactoring for us to do that. But let's check it out. Let's go back to PHP storm. And basically, I'm showing you this just so that you know how caching works. All right, so let's go to the index of the profile. And let's find where those figures are calculated. And here they are. Alright, so we are calculating the post counts, we're calculating the profile followers count. And we're calculating the user following count. But we can move this logic into the controller, let's move one at a time. So let me go into my profiles controller. Let's look for the index. There we go. The first one is posts. So I'm just going to say post count. So the post count is going to be equal to that. And we can replace this with post count. So we'll pass that in. And we'd need to pass that in here. So post count, let's replace follower count, cut, follower, maybe followers count with an S. Let's make a new one here for followers, count equal to the same thing. And let's go ahead and add that to our array here. So followers count, what else? We finally need the following count. So following count. All right, let's add that in following count. And let's also add that following count. There we go. So now we hit refresh. Yep, we get exactly the same thing, right. This whole refactor was not really for that. But rather, it was so that we could bring this into the controller, we can bring this logic into the controller. So how does caching work? It's actually quite simple. So we're going to use cache. And what we're going to use is this illuminate support facades, cache. So if we bring that in, now, notice up here at the top, it is being imported, so use illuminate support, facades, cash, so cash, and we're going to say, remember, and what's the key that we're going to use, alright, we need to make up a key a cache key, let's say count dot, post that, and then maybe the user ID, let's concatenate the user ID, that'll give us a unique key for each user. And then as a second argument, it's gonna be a closure. And then here, we're gonna return the same thing we had before. And that's it. So at that point, we are actually caching debt. However, we don't have access to user. So we do have to give user so let's say use user, that way it is available inside that closure. Alright, let me hit save. And let me go back here. And in telescope, we're going to take a look at cash. So in cash section, right, now it's empty. I'm gonna hit refresh, to a few arguments. Of course, I forgot to tell it how long to do it. As a second argument, we do need to tell it, how long we're going to store it for. So we can use levels now helper, and say, add seconds, and let's add 30 seconds. And then the function. Alright, so let me break this up into a couple of different lines. So it's easier to see. So we'll keep our key like so. And then we'll have the time. And then we'll have the callback. So there we go. So that's what it actually looks like. So we'll have post count is going to be equal to a cache that we're going to remember. And the key that we're going to use is count dot posts, dot and then whatever the user ID is, we're going to store it for now, plus 30 seconds. And then if it's not there, then this is what we're going to run. Alright, let's hit save and try that one more time. So we load perfectly fine. Go back here to telescope and it looks like count that post that three, it missed the cache, so it got set. I'm gonna go ahead and hit refresh here before 30 seconds go by, and now it hit. Alright, let's keep doing that. Let me see. All right, so hit again. Let's wait for those 30 seconds to be up. All right, and there. We missed the cache again, and we hit Set. So that's how caching works, it's basically going to throttle how many times we calculate those figures. So I need to do the same thing for the rest of these. So behind the scenes, I'm going to do the exact same thing to all of these right here. And there we go. So we are now successfully caching post count, followers count, and following count for each of our users. So let me go ahead and refresh this. So we can see it in action in telescope. So of course, we see that count that post that three missed, count that followers missed, count that following missed. So if we hit refresh, now we get those three in cache. So this is the type of performance enhancement that level offers out of the box to allow your application to run much, much faster, and not hit the database every single time. Now, there are many uses for caching. But I really just want to show you how easy it is to do. So in the case of cash, there is remember, and then there is the counterpart, which is remember forever, just keep that in mind. Remember, forever, does not have a count argument, and it will literally remember it forever. So if tomorrow, we decided that instead of 30 seconds, you wanted to add, say one day, you could say a day, you just say add days, you could say add months, add weeks, you could do just about any count that you want, based on now. So that works extremely well. And it's extremely simple to use. Now, we could probably refactor this into separate different methods, but I'm going to keep it like this. So it makes it very clear that we're caching each one of these variables. So with that, let's move on to the next thing. And what's that? Well, I want to start sending some emails. So I want to start sending a welcome email to anybody who registers in our free code gram application. So let's jump right to it. So let's do something. If you remember, whenever we register a new user, we hooked into the created model event to create our profile at the same time that we are creating our actual user. So why don't we use that again, to generate this email. So let's go back to PHP storm. And let's check out the user model. And right here, we are hooking up into the created method. So right now we are generating a profile. And then right after that, we can actually send out our email. Okay, so a couple of setup things about sending emails in development. So there is a service called mail trap, let's head on over to mail trap right now. And that is mail trap.io. Now, mailchimp.io is basically a virtual inbox, it is free to sign up, you can simply just sign up either using a Google account or a GitHub account. Or you can even do it by email. So I already have an account. So let me actually just log in. So there we go. This is what mail trap looks like. So inside this demo inbox, we have all of the credentials here that we need to actually set this up. Now the nice thing about using mail trap for your emails, is that level basically is already set up to do that. So it's very simple to set up. So let's jump back to PHP storm. And let's open up the dot CSV file. So right down here, mail driver is smtp. And you see that out of the box, it's set up for mail trap, the only thing that we need is just a username and a password. So let me go ahead and grab the username from over here, paste, and let me grab the password. Obviously, do not put what I have here. This is my account. In your case, of course, you would grab your username and your password. All right. So with that out of the way, how do we send an email in Laravel. So let us actually ships with a feature called mailable mails accept markdown. And if you're not familiar with markdown, the very quick Gist on markdown is that it allows you to do text formatting without actually having to do any HTML. So it's a very quick way for anybody that doesn't even know HTML to write properly formatted with bold, italics, unordered list code blocks, you name it, you could do all of that with markdown. So that's a nice thing and a nice feature. So for this course, we're not going to go super in depth on emails, but I do want to show you how to do a very simple out of the box mailable with Laravel. So let's jump to the terminal and let's run php artisan, we do have a make command for male. So let's run that now. php artisan help make male. And let's check this out. Obviously as always a name is required. And then we do have this dash M for a markdown. Now the nice thing with markdown again, is that level ships with a very nice template that you can use right out of the box. And as a matter of fact, I use this myself in actual production projects, and I haven't changed that much. It is a very nice looking template. And it just works out of the box. For email purposes on most applications, what comes out of the box is perfectly fine. So let's go ahead and run the actual command now. So let's run PHP, artisan make mail. And what are we going to call our mail? What about new user welcome, mail. And again, let's pass in that dash m flag. Now the dash m flag requires that you pass in where you want to actually store this particular mailable. And what it's ultimately going to be is just a view. So it's going to end up in your views directory. So I like to nest them inside an emails directory, and inside emails for now, let's just say, welcome email. Let's go ahead and create that. And let's see what Laravel whipped up for us back to PHP storm. Now we're going to be looking for two files here. First and foremost, in my app directory, we have a new mail directory. And inside there, we do have the new user welcome mail. And there it is not much to see here, right now. And then finally, if we go into our views, we do have this emails subdirectory. And inside there, we do have a welcome dash email. And if we open this up, you basically see it is just a blade component. So you may be wondering, Well, is there any way that I can actually see this in the browser, since it is an email, and sure enough, there is, let's go to the web, PHP, routes file. And right up here at the top, let's create a new, temporary, this is going to be temporary, but let's just call it slash email. And what we're going to pass in is simply return a new instance of that new user welcome mail. And if you do that, it will render that in the browser. So let's check that out. Back to Chrome, let's go ahead and just do slash email. And there we go. So that is the template that comes out of the box with Laravel. And to show you, let's go back here, let's change this to welcome to free code, Grant. Hit refresh, there we go. So you see that this is just a regular HTML template for your email. So let me go ahead and just change this body into a quick welcome email for anybody who registers to free code. So let's go back to PHP storm. Let's just say, this is a community of fellow developers. And we love that you have joined us, and maybe let's just get rid of this button here. And let's just say, All the best. And then I'll just sign it as Victor. Alright, so let's see what that looks like. So there we go. So welcome to the Free Code, Graham. This is a community of fellow developers. And we love that you have joined us all the best Victor. So that's it, that's probably good enough, as a welcome email. Again, we're not really focused on this template as much as just a logic of how to actually send this email. So now, let's actually set up to send this email, let's go back to this user model. And now there is something to be said about sending emails from a model. And in a real project, I probably wouldn't do it this way. But to get you started, we're gonna do it this way. So all you need to do is import the class mail, and it is illuminate support, facades, mail. Again, if we look up here at the top, we do have this import up here at the top. Alright, so with that, we can simply say, Alright, let's send an email to and what's the email address? Well, we can grab the user email, right? Because remember, we have the user it gets passed to us when this event occurs. So we're going to send an email to that email address. And let's send them new user welcome mail. And that's it. We are actually good to go on that one. So let's give it a go. Let's actually go back here to MailChimp. I'm going to refresh it. But notice that there's nothing here. And let me go ahead and register a whole new user. Let's go to the register route. And let's say new email, testing at test, Comm. New welcome email, put in a password. Go ahead and register. And now we get this authentication required. And you may be wondering, well, we did set that up in the dot E and V file. But here's one thing and I did set this up on purpose because a lot of times when you change your dot E and V file, it doesn't reflect and that's because you need to stop the process. Remember back here, we are constantly running this PHP, artists and surf. And if you don't stop this process, and then start it back up. It actually doesn't load up anything. In your dot E and V file. So let's go back here and hit refresh. And hopefully, this time, it will go through. So now one thing was we did air out, and the email was already taken, because we did create the account, we just didn't get to see the email. So let's say new welcome email to let's type in our password again. And I think this time, we'll be good to go. And sure enough, now one thing that did happen was that we still redirected to slash home. And I'll show you why in just a second. But if we flip over to demo inbox in mail trap, there we are, we did send out that email. How cool is that? Now one other thing that we can modify is this level up here, obviously, would probably want that to say Free Code grim. So let's go back here. And that is actually in the EMB file as well. So let's change this from Laravel. It's up here app name to free code, gram. And now if we come back here, now we do have that test route again, right? So we can hit the slash email, we still have that. But it still says Laravel. And you may be wondering, what does happen? Well, the same thing that happened with the authentication error, we just got, you got to go back to the terminal, you got to stop this process started back up again. And now. There we go. So when you hit refresh, we do see that happen. Alright, so one last thing that we can fix here. And we're just about ready to wrap it up. So after we registered, we still get redirected to slash home. The reason for that is that there is another controller, right here, HTTP controllers off, and there is the register controller. Now the register controller right up here at the top, where users get redirected after registration, we still have that s slash home. So let me go ahead and change that to just a slash. And sure enough, let's do the whole entire sequence to see what it looks like. So let's go to new user 123, testing 123 at test, comm testing user, but a password register, and there we go, it does go to our home. Now it does go to our home, but we're not following anybody. So of course, we don't see anything. However, we do know that we do have some profiles. And we do have other things that we can look at. So let's go ahead and follow this user. And now if we go back home, now we do see some posts right here. Which brings us to a good point, which is, we should probably maybe just have a couple of default things that always show up for our users, even though they may not be following anybody. It would be nice for that. But that is it for this lesson, if you stuck around for the entire time. Great, great, great job. This is some dense stuff. But once you start to get the hang of it, it really does become second nature and level makes development such an enjoyable process. And it is such an amazing framework to develop under I do it every single day. And it is always a joy to do. So with that. Just some final final thoughts. Where do you go next? Well, I do have a full YouTube channel. If you go to youtube.com slash coders tape, I do have a full channel full of Laravel videos, everything from scratch. My channel has a ton of videos on Laravel. I have a whole package Development Series, I have a whole collections guide. And I add videos all the time. So please, if you liked this course, go ahead and subscribe to my YouTube channel. Furthermore, if you go to github.com, slash coders tape slash Free Code gram, I do have the full code for this course, everything that we worked on from scratch, I've shared all the code here with you. So if you get stuck or anything like that, this would be the first place for you to go and check to see how your code is different from the one from the course. So it is a great resource, you're definitely going to want to check that out. And finally, one last thing, if you do get really serious about learning Laravel, you need to read the Laravel documentation. Go ahead and start from the top, go to the getting started. Click on installation, and go ahead and read the entire thing from top to bottom. Laravel is known for having some of the best documentation in the open source community. So definitely, definitely I recommend that you read this entire documentation. What else do you need to know? Well, there is something called Laravel dash news, the source for anything related for Laravel news. So go ahead and subscribe, they do send out a newsletter is a great way for you to be able to keep up with anything going on in the Laravel community. And last but not least, not to sound like a broken record. But go ahead and subscribe to my YouTube channel. I promise you, I'll make it worth your while and I will always have high quality content. So if you subscribe, of course, you'll be amongst the first to see this new content. So with that, we'll wrap it up. My name is vector. It's been a pleasure and I'll see you next time.
Info
Channel: freeCodeCamp.org
Views: 1,632,597
Rating: undefined out of 5
Keywords: laravel, laravel from scratch, laravel series, laravel tutorial, laravel project, php, laravel php, php framework, mvc, model view controller, laravel 5, laravel course, laravel for beginners, instagram clone, instagram clone laravel, laravel 5.8, php tutorial
Id: ImtZ5yENzgE
Channel Id: undefined
Length: 265min 5sec (15905 seconds)
Published: Tue May 07 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.