All right. Is this thing running? Recording? We're good? I don't know how much time we have. Oh, I need to close those curtains, too. They could be here any minute. But I didn't want to leave you hanging. We can't have a 30-days course with only 29 days. So here's the deal. If anybody knocks on your door, we never met. You don't know Larrakess. Okay. We may have to go quick, but let's get started. Now, I do have one compromise we need to make in order to fit all of this in to a single video. And I'll show you. Now, here is my Laravel herd root directory. And yeah, you can see pixel positions. But I also have a backup version where I've been working behind the scenes to save us just a little bit of time. So we're going to go into Resources, Views, Components. And just this once, I'm going to ask forgiveness for copying a bunch of form-related components so that I don't Auth Routes and Controllers 0:49bit of time. So we're going to go into Resources, Views, Components. And just this once, I'm going to ask forgiveness for copying a bunch of form-related components so that I don't have to manually type them out. Trust me, we'll quickly go over it. But you've seen this before. You're already familiar with it. Let's skip over this process. So I will copy this directory, switch back to our real project into Resources, Views, Components, and I will paste it in. And yeah, we'll talk about this more in a moment. Cool. So now, let's start with authentication. I'm going to go into my routes file and let's set up our endpoints. And I'm going to do these all at once, again, to save a bit of time. So register will hit a, how about registered user controller. Again, this is a recap of the authentication episodes. And this will hit a create action. Next, when you post toregister will hit a, how about registered user controller. Again, this is a recap of the authentication episodes. And this will hit a create action. Next, when you post to that endpoint, that will hit a store. So we are storing a new registered user. And of course, ignore the squiggly lines just for a minute. Next, login. So if you make a get request to login, this will hit, again, auth controller, login controller, session controller, whatever you want. This will hit a create action because we are creating a new session. That's how I think of it. Next, when you post to that endpoint, that will hit a store action. And then finally, let's do a delete request to slash log out. And yeah, that will hit a destroy action. All right, let's create these controllers now. PHP, Artisan, make me a controller called session controller. And let's set up a full resource for it. And then let's dodestroy action. All right, let's create these controllers now. PHP, Artisan, make me a controller called session controller. And let's set up a full resource for it. And then let's do another one, but this time for registered user controller. All right. So yeah, let's import these. And let's start with registration. All right. And later, of course, we will remove any actions that we don't make use of. All right. So this is going to load. How about auth.register? In this case, I'm going to use a different directory name, and that's fine. And also, again, in the spirit of saving time, I'm going to make use of my editor a bit more. So in this case, I can option click and create the view all at once. And you'll see it automatically creates the auth directory in that file. And that's going to help us a lot. All right. So let's create a layout. And yeah, let's start with a page heading. We'll call it register. Registration Form Components 3:02creates the auth directory in that file. And that's going to help us a lot. All right. So let's create a layout. And yeah, let's start with a page heading. We'll call it register. And yeah, how about font bold? Let's center the text. I want it pretty big. So how about text for Excel and a little margin below it? OK, so I can imagine that this is a standard page heading, which means why don't we move it into its own component like this page heading that blade that PHP and paste it in. All right. Now this will be our slot. Cool. So now if I switch back, we can swap it out with page heading. OK, now I'm going to use some of these form components. So again, if you take a look at them, you've done these before, right? This is what a button looks like. And mostly we're just extracting and tailing classes. But we do have a couple of things that might be nice. So I have one component called form, and this will create alooks like. And mostly we're just extracting and tailing classes. But we do have a couple of things that might be nice. So I have one component called form, and this will create a form and add some default classes. And then it also handles figuring out whether to add the CSRF hidden field and the method field. So notice it defaults to a method of get. But if we change that to post or put or patch, as long as it's not get, it knows that we always need to include these two things, which you learned about in the forms lesson. But yeah, other than that, here's an input. So I create a field and a field is just a wrapper for an input. It contains a label, it contains the input itself, and it contains an error. You've seen this a million times. And if you want, visit GitHub and you can inspect it and copy it over to your project. OK, yeah, once again, it's going to save us so much time. Just give me this one.times. And if you want, visit GitHub and you can inspect it and copy it over to your project. OK, yeah, once again, it's going to save us so much time. Just give me this one. All right, so let's build up our forms. And do note, whenever you have a component within a directory, you need to do the directory name, dot, and then the component name. All right, so the method in this case is going to be post and the action is going to be register. All right, so first up, I'm going to need an input. And for my inputs, I accept a label and a name, and it takes care of the rest. So the label is going to be your name and then also the name for the input, which just happens to be name in this case. All right, let me show you what this looks like in the browser. If I visit slash register. Yeah, there we go. Looks good to me. All right, back to PHPStorm. All right, next. And actually, real quick, let's just stick with name.like in the browser. If I visit slash register. Yeah, there we go. Looks good to me. All right, back to PHPStorm. All right, next. And actually, real quick, let's just stick with name. That way, this one can be email. Now, in this case, the type for the input should not be text. It should be email. All right, next, I want two more. So we will have one for the password. And then also you have to confirm your password. So password confirmation. All right, password and type for the input is also password. And this is password underscore confirmation. And make sure it takes the same shape. All right, next down at the bottom, we could have a form button and this could say create account. And let's have a look. Yeah, name, email, password, and create account. But notice there's no padding at the bottom. Maybe I could add a little padding to the body here. I think that's OK. PB10, just to push it down a little bit. And that's fine.and create account. But notice there's no padding at the bottom. Maybe I could add a little padding to the body here. I think that's OK. PB10, just to push it down a little bit. And that's fine. Maybe even a little more, actually. Yeah, that's good. Now, think about it. When you register, you also need to create an employer. So I have a divider component and that just creates a little line, as you can see right here. Yeah, just a little divider. And then we're going to have a section for the employer details. For example, let's copy this. I need a name for your employer. So how about employer name? And the name for this input will be employer. And then also we need one for the logo. So I will call that logo. And this is a file input. So I'm going to set type to file in this case. So, yeah, notice any attributes I provide here, of course, will be passed through here. And that's how attributes works. In this case, I'm just extracting the default into itsin this case. So, yeah, notice any attributes I provide here, of course, will be passed through here. And that's how attributes works. In this case, I'm just extracting the default into its own array so that it's easier to consume. And that's a good approach you might want to take. All right, back to Arc. So we have all of this and then the employer name and logo. All right, next, as you probably know, anytime you have a form that will accept a file upload on the form tag itself, you need to set the type to multipart slash form dash data. And that's just how it will be encoded in this situation. Pretty standard HTML stuff there. All right. So let's go to registered user controller. And when we submit that form, we will now hit this endpoint. So let's die and dump all of the request data. All right. Magic. I'm going to fill out this form. All right. Let's create the account. And there we go. We have our attributes. While we're here, Registration Validation and Uploads 7:38So let's die and dump all of the request data. All right. Magic. I'm going to fill out this form. All right. Let's create the account. And there we go. We have our attributes. While we're here, notice that logo is actually an instance of a Laravel class called uploaded file. And you're going to love this. It's going to make it as easy as possible to store this image wherever it needs to go, whether it's publicly available or even uploaded to Amazon S3 or something like that. All right, let's get to work. So this time, why don't we use requests not as a helper function, but instead using an object instance like this. So we're going to validate. And by the way, the API is identical. Okay. Let's see if my editor can help me a little bit with the rules. We want to save time anywhere that we can. Yeah. It's not perfect, but it'll get us going. Okay. So validate the name, the email, email verified at is not required, nor is rememberWe want to save time anywhere that we can. Yeah. It's not perfect, but it'll get us going. Okay. So validate the name, the email, email verified at is not required, nor is remember token. Password is required and it should be confirmed. And then I'm going to use the password validation rule. Make sure you don't accidentally grab the password facade. You want to illuminate validation rules, password, and I'll set. The only requirement is it needs to be at least six characters. Next. What else? Email. Let's ignore the maximum for now. And it should be unique on the user's table and specifically on the email column. This is actually automatic because it will fetch that from the name. But if you want to be explicit, yeah, this is just saying, Hey, look in the user's table and see if there's any email field that has the current email. And if there is, that's a no-go. We can't have two users in the system with the exact same emailHey, look in the user's table and see if there's any email field that has the current email. And if there is, that's a no-go. We can't have two users in the system with the exact same email address. It needs to be unique. Okay. But next you'll remember, we also have employer specific validation. So we have a couple options. We could group them all together. Or what if we tried this, let's say user attributes, and then I will do another one for the employer like this employer attributes. And this can change too. And actually let's get a PHP storm to do it. Some rules for the employer. And yeah, we just need this here. All right. So you have to give us a name and you have to give us a logo. We'll make that required for now, but also I want to ensure that this logo is in fact an image for that I can use a file rule, illuminate validation rules file, and let's set the available types. And yeah, you can give us a PNG, whatever you want here, a JPG, WebP,is in fact an image for that I can use a file rule, illuminate validation rules file, and let's set the available types. And yeah, you can give us a PNG, whatever you want here, a JPG, WebP, anything you want to add there, maybe a WebP too. And that'll be enough. Now here's why we split it up. I can now do things like this user create user attributes, whereas otherwise I'd have to do something like array except or something like that to omit these from being passed to user create and the same for updating the employer. So this just makes it a little bit easier. Create a new user, then log in the user off, log in the user. And then, yeah, let's create the employer. Yeah, we'll do that right here. So we'll say user employer create. And yeah, because we are accessing the create method in this way, it will automatically assign the user ID to the employee record. That way I don't have to manually set it. It happens automatically. Now we could doaccessing the create method in this way, it will automatically assign the user ID to the employee record. That way I don't have to manually set it. It happens automatically. Now we could do something like this where we set employer attributes. But in this case, we need to do a bit of work first for the logo. I need to store the logo in the proper location. And then wherever that path is, I want that to be referenced within the employer's table record. So here's what we'll do. Now, you'll remember that the request logo field when we saw it in the browser actually was an instance of Laravel's uploaded file class. And that's really cool because now we have some behavior on that class to store the image wherever it needs to go. I'm going to put it in a folder called logos. OK, let's talk about this. If I go up into my config directory, there is a file systems configuration file. So this is for storage. Do we want to store files locally or with FTP orcalled logos. OK, let's talk about this. If I go up into my config directory, there is a file systems configuration file. So this is for storage. Do we want to store files locally or with FTP or S3? It just depends on what you want to do. And I can see the settings for each of those disks or drivers here. So yeah, in our case, these will be publicly accessible avatars. So I want to use the public disk by default. So I can set that within my environment file. And yeah, notice file system disk. I will update this to public. All right. And that's it. Believe it or not, you're really going to love this. So when we upload the image, it will be saved within the storage app public and it will create a new logos folder. And then we will create a symbolic link from here to the public directory so that any person can access these images. That's the way that works. All right. Now, once it uploads the image, it will save a path to where that logo is located. So I can thenthe public directory so that any person can access these images. That's the way that works. All right. Now, once it uploads the image, it will save a path to where that logo is located. So I can then pass that to our create method. All right. So the employer's name will be employer attributes name, or, of course, you can grab it right off the request. And then the logo will be, assuming we did everything properly, the logo path. All right. So validate all of the attributes, create a user, store the logo, create a new employer. And then how about redirect to the homepage? All right. Let me take a look at this. Good, good, good, good. And create. Oh, actually, no, employer attributes should be employer. That was the name of the input we assigned within the view. Other than that, I think that looks pretty good. All right. So it looks like we have only two actions here. So I can get rid of this and this. And yeah, from now on, I will do this behind the scenesthan that, I think that looks pretty good. All right. So it looks like we have only two actions here. So I can get rid of this and this. And yeah, from now on, I will do this behind the scenes after the video, again, to save us a little time. Let's give it a shot. All right. Create the account. And it fails. So maybe it wasn't called employer. Let's have a look. Let's go into register, employer name. Yeah. Employer logo. All right. Let's go back to registered user controller. Ah, yes. I bet you saw that. All right. So, of course, that key wasn't available. All right. Try it one more time. All right. And there we go. So, yeah, I'd like to see a little more feedback, and we can do that through flash messaging. But if I switch to users, sure enough, I have a new John Doe account. The password is hashed. And we also have an employer who belongs to that user. So I think we're all set for registration. Next, I will switch over to login and log out. Login, Logout, Middleware 13:57John Doe account. The password is hashed. And we also have an employer who belongs to that user. So I think we're all set for registration. Next, I will switch over to login and log out. So let's go into session controller. For create, this will hit auth.login. And let's create that. All right. So let's steal a little bit of the code here. So this will say login. And this time, we will post to login, and there is no file input there. Okay. I think all we need is an email address and a password. All right. How's that look? I think that's right. All right. Back to session controller. That will now hit a store action. And you know what? We already wrote this functionality in the authentication episode. So if I switch to GitHub, where we have the source code for the entire series, if I go into app, HTTP, session controller, I bet, you know, let's take a look at this. It's all the same stuff,So if I switch to GitHub, where we have the source code for the entire series, if I go into app, HTTP, session controller, I bet, you know, let's take a look at this. It's all the same stuff, right? Show the login view, validate the request. So let's take the raw data here, copy it, and see if we can just paste it in here. All right. So, yeah, that looks pretty good. We try to log the user in. If we couldn't, then we attach a validation error to email. We regenerate the session token, as we learned, that's a good practice. And then we redirect again to the homepage in this case. And then finally, for destroy, yeah, you just do off logout and redirect, and you're done. So that saves us a bit of time, which we needed. Let's have a look. Let's go to slash login. Let's try to log in john at example.com. And we're in. All right. Very cool. But yeah, notice how if I visit slash login,Let's have a look. Let's go to slash login. Let's try to log in john at example.com. And we're in. All right. Very cool. But yeah, notice how if I visit slash login, I still see that form, which doesn't make sense. So let's do a little bit of authorization. If you think about it, to access this page, you should be a guest. Same for this one, but not for this one. Actually, in this case, you need to be signed in. So let's say middleware off. And then for these two, and actually also for these two, you need to be a guest. If you're signed in, it doesn't make sense to visit a register page. So I'm going to use a route group, but first add a middleware. And we'll say you got to be a guest in order for this to work. Okay. So now any route nested within this closure will receive the guest middleware. And this is a wrapper or instead for each of these routes, we could do something like this. And that would doOkay. So now any route nested within this closure will receive the guest middleware. And this is a wrapper or instead for each of these routes, we could do something like this. And that would do the same thing. All right, very good. Next, let's go into our layout file. And here is our nav section. So yeah, right here, why don't we tweak this, I only want to see this post a job link if you're signed in. So I'm going to use this off directive, like so. And then I'm going to add another one here called guest. Now I could do off else and off. But sometimes I think this reads a little bit better. If you're a guest, show this, if you're signed in, show that. And actually, while we're here, why don't we say job slash create for the posted job link, because we know that's what it's going to be ultimately. Okay. Now, if you're instead a guest, let's repeat some of this here. All right, so we will have two links to sign up or log in. All right,that's what it's going to be ultimately. Okay. Now, if you're instead a guest, let's repeat some of this here. All right, so we will have two links to sign up or log in. All right, so sign up would be slash register, and login would be slash login. Let's have a look. Okay, so if I refresh, yeah, I still see post a job because of course, I'm signed in. But let's open up an incognito window. And yeah, now, because we're not signed in, I do see sign up and login, and those do work. Perfect. All right, so let's close those out. And I'm back to the view where I'm signed in. All right, five second breather real quick. I get it. I know I'm going really fast. Sorry, it's got to be that way. It's day 30. We got to wrap up. Okay, back to work. What should we work on next? How about this big search bar here? Yeah, okay. Let's go into job slash index. And let's see what we have. Yeah, right now we have standard form tags. Search and Tag Filtering 18:02What should we work on next? How about this big search bar here? Yeah, okay. Let's go into job slash index. And let's see what we have. Yeah, right now we have standard form tags. But I'm going to replace this with our new xforms.form tag. And this will make a get request, which is the default. But I want to send it to how about search, and we will implement that route. All right, next within here, let's add an input. The name will be q for query. That's really common. The placeholder can be something like web developer. And let's have a look in the browser. Ah, I get undefined variable label. Yeah, so my input component is expecting a label. But in this case, we don't actually want one. So if I switch through, we can see that the label is passed to this field component. And the field component checks whether label is truthy. Okay, so if I switch back, all I need to do is set label to false. All right, switch back. And that solvesthis field component. And the field component checks whether label is truthy. Okay, so if I switch back, all I need to do is set label to false. All right, switch back. And that solves that problem. Okay, I think I need a little more breathing room below the title. So why don't we say class of MT6. And yeah, we kind of reproduced what we had before. Cool. So now, yeah, take a look. If I search for how about Laracast, and I hit submit, I do get a 404 because I haven't yet implemented that route. All right, let's do it now. Let's duplicate this. If you visit slash search, again, keep it very simple. Let's load a search controller. And actually, this time, I'm going to show you invocable controllers. So every once in a while, you will have a controller that will only ever have one action. In these cases, rather than passing an array and the action name, you can just pass the path to the class itself. And then an invoke magic method will be called on that class.ever have one action. In these cases, rather than passing an array and the action name, you can just pass the path to the class itself. And then an invoke magic method will be called on that class. It's pretty cool. Let's do that now. php artisan, make me a controller called search controller. And oh, you know what, that's interfering with my route declaration. So let's do that first, and then uncomment this. Okay, now I can import it, and I will command click through. And yeah, if I create a magic underscore underscore invoke method, now, this will be called. And yeah, this is this is great for situations where a controller only ever needs to have one action. So I'll show you, come back, give it a refresh. And we now have hit that invoke method. Okay, so there should be a queue query within the request, refresh. And now that is set to layer casts. And of course, we can control that here. Cool. So now we have everything we need to search our jobs table.a queue query within the request, refresh. And now that is set to layer casts. And of course, we can control that here. Cool. So now we have everything we need to search our jobs table. And this will be fairly primitive. We're not going to use full text search or anything special. We'll just say, look for any job where the title is like this search param. And that should be enough. So let's say job where the title is like the request query. But then I'm going to say, yeah, any number of characters can come before that query, and any number of characters can come after it. So as long as this search query exists somewhere within the title, I want it included in the result set. So we will fetch that. And then why don't we return that as Jason so we can have a look in the browser. Let's start from scratch. Let's look for something related to how about teacher. All right. We run it. Let's do pretty print. And we get one result. All right. So nowa look in the browser. Let's start from scratch. Let's look for something related to how about teacher. All right. We run it. Let's do pretty print. And we get one result. All right. So now we just need to render a view to display those results. And that should be pretty easy. Let's return a view. And this could be like a generic view, like results. Anytime you want to show jobs, we can use this view. And I'll pass through our list of jobs. Nice and easy. All right. Let's have my editor create the view. We'll have our layouts. We will have a page heading results. And then let's do this. Let's go into job slash index. And yeah, we want this right here. So I'm going to copy this and paste it in. And I don't think we need that MT6 in this case. All right. Yeah. Let's have a look. Back to the browser. Refresh. And we have only one result. But it does seem to be working. Let's try one more time. Something related to tax. And once again, we have one result. Buthave a look. Back to the browser. Refresh. And we have only one result. But it does seem to be working. Let's try one more time. Something related to tax. And once again, we have one result. But yeah, that's working. Cool. Search is now done. At least the primitive form of search is now complete. We should also look for tags and things like that. But you can work on that on your own. So now think about it. If we go back to our ROPS file, let's set up another route for tagging. So I could say visit tags slash and then some kind of tag name. That will hit a tag controller. And I will create that. So make me a controller called tag controller. Cool. And let's import that. And yeah, this will be the exact same thing. So in fact, if I go to search controller, let's just copy that. Switch back to tag. Paste it in. And now we aren't searching the database. We are finding all jobs associated with a given tag. Something like that. Okay. So let's go to ourlet's just copy that. Switch back to tag. Paste it in. And now we aren't searching the database. We are finding all jobs associated with a given tag. Something like that. Okay. So let's go to our tag model. And we don't yet have a relationship between a tag and a job. But I think we do in reverse. Yes. So let's copy this. Bring it over to tag. Paste it in. And now if I have a tag and I want to find all jobs, it's also a belongs to relationship. We just have to reverse it. Like that. All right. Back to tag controller. All right. Well, now I'm going to ask for the tag. And you learned about this through route model binding. Just as a five second recap. Yeah, right here. Because we have this wildcard here that's called tag. And then we have a parameter name also of tag. Laravel is going to try to track down this tag for us. But by default, it's going to expect this wildcard to be an ID. So I can add a colon and say, no, actually,name also of tag. Laravel is going to try to track down this tag for us. But by default, it's going to expect this wildcard to be an ID. So I can add a colon and say, no, actually, the identifier here is name. So if I visit tag slash front end, yeah, I basically want Laravel to say select star from tags where name equals front end. Yeah, without that, it would default to this. And yeah, we already reviewed this. So that should be a recap. All right. So now I should have the tag. I should be able to get the jobs for the tag. Right. So why don't we just do this? Load the results and pass through all of the jobs associated with this particular tag. All right. Let's clean up. And it's so easy, isn't it? It kind of blows me away. It's so simple. All right. Back to the browser. And let's visit some random tag. How about UT? All right. And here are all of the jobs that are associated with that particular tag. Yeah, cool. So now, yeah, Job Posting and Final Tweaks 24:55Back to the browser. And let's visit some random tag. How about UT? All right. And here are all of the jobs that are associated with that particular tag. Yeah, cool. So now, yeah, all of these tags should be clickable. So if I click here, that will show me all of the jobs so that I can further filter things down. That's great. OK, final thing. And then I promise we're going to be done. Of course, we need to implement the form to post a job. So let's do that now. Go to my routes file. And we'll say right up here. How about this? Let's duplicate this job slash create. We'll hit job controller at create. And then I'll do another one here. When you make a post request to slash jobs, that should store a new job in the database. And of course, these need to have the proper middleware. In order to post a job, you need to be signed in. All right. Let's take care of it. So we have our create action that will return jobs dot create. Let'sneed to have the proper middleware. In order to post a job, you need to be signed in. All right. Let's take care of it. So we have our create action that will return jobs dot create. Let's have my editor create the view x layout. Notice how quick we can be when we when we have our systems in order. Right. Let's do a page heading, new job and sanity check. Let's load the page job slash create. That works. And further, if I click right here, it should load it. Cool. Let's build our form. Now, this is going to make a post request to slash jobs. And let's do this again. I'm going to save ourselves some time. You've already seen the basic process of creating a form input. So I will paste in a few at once. So we have one input for the title and a salary and a location. Next, we need one for the URL. So this is the URL to view the actual job page on your company's Web site. Next, when you create a job, you can optionally add a number of tags. So I'mlocation. Next, we need one for the URL. So this is the URL to view the actual job page on your company's Web site. Next, when you create a job, you can optionally add a number of tags. So I'm going to keep this very simple. It's just an input. And if you provide a comma separated list, we will turn those into tags. Maybe not ideal, but it'll get the job done in this case. Next, I'm going to have a button to publish the job. And then I'm going to introduce a new one, which is a select field. So if I have a look at it real quick. Yeah. Notice it's just deferring to an HTML select. All right. So our options are part time and full time. And this is where you specify what the schedule for the job is next to write down here. Let's add it. I'm going to add a checkbox once again, input and type equals checkbox. Very basic stuff. OK. So the label for the checkbox is feature and cost extra. Yeah. Presumably if you built this on your own in order to feature a job,once again, input and type equals checkbox. Very basic stuff. OK. So the label for the checkbox is feature and cost extra. Yeah. Presumably if you built this on your own in order to feature a job, you're going to be charged one hundred dollars or twenty dollars, whatever it is. We would want to note that. But yeah, we're not going to deal with billing or stripe in this series. It's far beyond the scope of this course. Anyways, I think that's it. So the only thing I might do is add a divider to separate the main fields from the optional tags. All right. Let's have a look in the browser. And here we go. To create a new job, you got to give us all of this junk here and then you can publish it. All right. So that's going to make a post request to slash jobs that will hit our job controller and that will load this action. Now, you can see here we have a form request. I actually didn't review that in this course. Some people like them. Some people don't. I wouldour job controller and that will load this action. Now, you can see here we have a form request. I actually didn't review that in this course. Some people like them. Some people don't. I would encourage you to take a look at them. But for now, I'm not going to dig into anything new. So let's stick with the standard Illuminate HTTP request. All right. Let's get to work. We will validate the request. Let's see what my editor can do for me. I'm going to add a new job. Yeah, pretty good. I will take care of the employer ID. So you need to give us a title, a salary, a location, a schedule. And then for our demo, at least we're saying, well, the schedule needs to be either part-time or full-time. So one way we can do that is through the Illuminate validation rule class. And I can say it needs to be, the attribute value needs to be included in one of these. And we can also set this up as an enum if we want, but I'm not going to.validation rule class. And I can say it needs to be, the attribute value needs to be included in one of these. And we can also set this up as an enum if we want, but I'm not going to. All right. Next step, the URL is required and it should be a URL. Or if you want to make sure it's an active URL, you could do that as well, which is cool. And then featured, I will handle that a little differently. Finally, we have tags and we'll keep it here. And let's say tags actually can be nullable. All right. Next, I will save that to attributes, and then I will manually handle the featured status. So I could say, okay, attributes, add a new one called featured, and that will be true or false depending on whether the request has a value for that featured checkbox. Remember, if that input isn't checked, I don't think anything gets passed, right? But if it is checked, it's set to on or something like that. All I want in this case is a Boolean.checkbox. Remember, if that input isn't checked, I don't think anything gets passed, right? But if it is checked, it's set to on or something like that. All I want in this case is a Boolean. So we will use that. All right. This looks good to me. So let's go through the authenticated user. Let's grab the employer. We'll reference the jobs relationship and create a new one there. And again, to be crystal clear, when we take this pathway, when we create the job, the employer ID will automatically be set in the process. And further, when we access the employer through the authenticated user, we remove any opportunity to fake who the current user is. Unless you're signed in, you have no ability to create a job under a different employer. Okay. So it sounds like we just need all of these attributes, maybe except the tags. So here's what I'll do. This time, array, accept, and I'll provide the attributes and then the one that I want to exclude.like we just need all of these attributes, maybe except the tags. So here's what I'll do. This time, array, accept, and I'll provide the attributes and then the one that I want to exclude. We could do that, or we could access it through the request. I think there's a request unless or a request except method as well. So either of those would work. All right. Now we have a new job record. The final step is tags. So why don't we do this? Let's see. Do we have any tags at all? And what we'll say is if we don't have anything there, let's just assume false. I'm not sure if that's necessary. We might be able to remove that, but I'm going to keep it. Then what I'm going to do is basically explode that list of tags using a comma as a separator, something like this. So now Laravel backend front ends that will turn into an array, right? Of Laravel backend. You get the idea. Let's then loop over it. So for each of those as tag, then let'ssomething like this. So now Laravel backend front ends that will turn into an array, right? Of Laravel backend. You get the idea. Let's then loop over it. So for each of those as tag, then let's create a new tag. So I need a job instance. We got it here and I can say job tag. And yeah, you'll remember using TDD, we implemented this tag method and this will try to find a tag with the name and attach it. Otherwise it'll create a brand new tag in the database with that name. So yeah, on this note, keep in mind, this is fairly primitive. We could end up in situations where, for example, you have a tag called front ends in the table, but then this as well. And we should consolidate that as much as we can, but we're going to take a shortcut where we can find it. All right. Let's pass it in. And I think we're done. So let's redirect to the home page when we're done. Okay. Let's get rid of all of these. And this is our, let's clean this up.it. All right. Let's pass it in. And I think we're done. So let's redirect to the home page when we're done. Okay. Let's get rid of all of these. And this is our, let's clean this up. This is our job controller. All right, let's go. Post a job. I'll fill this out like magic, like so. All right. So we have a position for Laracast video editor pays 90 grand. Here's the link to the work page. And here are some optional tags. Let's publish it. All right. I would expect to see it right here, right? Well, let's see. Where is it? Ah, it's at the end of recent jobs. Here's what I think I did wrong. Let's go into job controller and maybe I got the order wrong. Maybe recent jobs is actually first and featured is second. Yeah, I bet that's what I did. Okay. Back to arc, give it a refresh. And again, I don't see it here, but I do see it at the end. Okay. So we just need to reverse the order. Why don't we say the newest jobs show up top job? IBack to arc, give it a refresh. And again, I don't see it here, but I do see it at the end. Okay. So we just need to reverse the order. Why don't we say the newest jobs show up top job? I want the latest ones and give me the results and group them according to whether they are featured or not. And that should do it. Come back, refresh. And there we go. We have our brand new job. So let's see. Can I view all jobs associated with that tag? Yes, I can. Now I should be able to click on the job and it will take me to the job listing page. Let's fix that. And then I promise we are done. All right. So here is the H3. It's now going to be an anchor tag that links to the jobs URL like so. So let's do the same thing for job card wide, like so, and cross your fingers, refresh, click on this, and it loads the layer cast page where you can view more details. The only thing you might want to do is set a target of blank for both of these. Switch over to thisrefresh, click on this, and it loads the layer cast page where you can view more details. The only thing you might want to do is set a target of blank for both of these. Switch over to this one as well. And that way, some people don't like this, but in this scenario, I think it's okay. That way the user doesn't completely abandon your jobs page. It instead opens the job within a new tab. So again, imagine you're looking for jobs related to video work. All right, here we go. Click on it. And now we can review more. And ladies and gentlemen, that is all I'm going to cover today. Oh, wait, actually, no, no, no. I have two more things. Sorry. Two more things to show you. We have to update the job card to show the new employer logo. And then I also want to display a logout link and make a couple tweaks to make our query performance better. All right. Let's go into employer logo. And yeah, right now we are hard coding the path, but now we can swapdisplay a logout link and make a couple tweaks to make our query performance better. All right. Let's go into employer logo. And yeah, right now we are hard coding the path, but now we can swap it out with the employer logo. Okay. So now let's ask for an employer when you load this component. Okay. I believe we referenced it in job card. Yep. Let's pass through the employer. Job employer. And then I think we do the exact same thing in job card wide. So I'll paste that in and remove the width. Okay. So now let's switch into our component. And I'm going to pass this to Laravel's asset function. And that will prepare a full URL to the asset. And remember, when you upload a logo, it goes into the storage app public logos directory. So here's one of the logos I uploaded. And now all you have to do is sim link it into your public folder, which is globally accessible. So for that, you can say php artisan storage link. All right. So now notice we have a symbolicAnd now all you have to do is sim link it into your public folder, which is globally accessible. So for that, you can say php artisan storage link. All right. So now notice we have a symbolic link right here. Yeah, there it is. And now they're accessible. All right. Let's go to arc. And we see it, but the size is wrong. All right. Let's go into employer logo. And yep, we accept a width, but we never used it. So let's do that now. Come back. And that looks good to me. All right. Next, let's go into job controller. And remember to always optimize your queries. If we have a job and we're going to access tags and employer information off it, if we're not careful, that's going to lead to an N plus one problem as we learned about. So let's always use the width method to eager load any relationships we require, such as employer and tags. And yeah, you would also do the same thing, for example, in searchSo let's always use the width method to eager load any relationships we require, such as employer and tags. And yeah, you would also do the same thing, for example, in search controller. So make sure you say width, employer and tags and whatever else you happen to reference. And when these queries get a little long, yeah, make sure you can put them on their own line. And if you want, you can even call this query method to start a new query. And that allows you to keep all of your primary filter methods on their own lines. And that does the same thing. All right. Last thing, and then I promise this time I'm letting you go. If we switch to arc, yes, we have sign up and log in. But if I log in as john, there's no link to log out. So that's my final step. If you're signed in, I'm going to add a form to log out. That'll hit the logout endpoints. And it's going to make a POST request.So that's my final step. If you're signed in, I'm going to add a form to log out. That'll hit the logout endpoints. And it's going to make a POST request. But of course, we need to add the CSRF and method tags. And yeah, we're not using the form component because that has some styling for the form itself and the button. And we don't need that in this case. Okay, so yeah, now let's do a display of flex. And yeah, it looks good to me. So I can post a job or I can log out. And this time, ladies and gentlemen, I'm done. I can't do any more in this course. Well, I can't believe it. But we are now officially positively, undeniably, indisputably, irreversibly done with 30 days to learn Laravel. It has been a massive effort for both you and me. So if you have made it through all of these 30 days, trust me, I've watched a lot of courses myself, and rarely do I complete them. So whether youa massive effort for both you and me. So if you have made it through all of these 30 days, trust me, I've watched a lot of courses myself, and rarely do I complete them. So whether you intended it or not, I'm going to take that as a compliment. Alright, so let's talk about this. Come here. I have recorded iterations of this course for about 10 years now. It goes all the way back to 2013 with Laravel 3 from scratch, if you can believe it. And yeah, it never fails. Every single time, people will complain that we didn't cover such and such topic. You know, there's nothing here about package development. What about APIs? What about events? You didn't talk about Livewire or Inertia. How come? And I'm going to tell you the answer to that question right now. The reason is because we didn't. Well, okay. You know, as the saying goes, your learning doesn't conclude the moment you finish a beginner-related course. I'm sorry toright now. The reason is because we didn't. Well, okay. You know, as the saying goes, your learning doesn't conclude the moment you finish a beginner-related course. I'm sorry to say it has only just begun. So yes, I would encourage you to learn more about Livewire, and we have a course for that on Laracast. Yes, you should learn more about API development, and we have a course for that. Yes, you should learn more about Inertia.js, and we have a course for that. But do they belong in a beginner-specific course? Well, that's up for you to decide, but I chose no. There is such a thing as giving people too much all at once. And I would rather you complete a course and then move on versus become overwhelmed by the material in one course. Okay. So this is somewhat of a bittersweet moment for me, because I know most of you are watching this as a free course, maybe even on YouTube,by the material in one course. Okay. So this is somewhat of a bittersweet moment for me, because I know most of you are watching this as a free course, maybe even on YouTube, and you're never going to sign up for Laracast. Even though, did you know that you can sign up for Laracast for $15 a month? 15 bucks. I went to Subway yesterday and it was 15 bucks. You could access everything we have ever created for 15 bucks a month. But I already know most of you won't. Some of you will, and I immensely appreciate it, but most of you won't. You'll finish this video. You're probably already done. You're probably not even listening to me at this point. You've already moved on to something else, and we'll never see each other again. And that is a bittersweet moment. So I'm going to finish up with a song to show you how I feel when you don't sign up for Laracast. Let me show you.And that is a bittersweet moment. So I'm going to finish up with a song to show you how I feel when you don't sign up for Laracast. Let me show you. Oh my God, they're here. Push me off.