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.