Laravel Blog: Roles & Permissions, Likes & Dislikes, View Count | Part 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I'm building blog websites with admin panel in lateral 10. if you haven't watched the first part click right here in this video we are going to add user registration login email verification password reset with alarable Breeze we will install spotty permissions package and create user and admin roles and restrict access to admin panel we will Implement post likes and dislikes using laravel Livewire we will count number of views on post and then in admin panel we will output analytics such as number of views number of likes or dislikes for each post we will Implement brand new homepage with four main sections latest article the most popular three articles based on likes recommended articles based on user likes history if the user is authorized if the user is guessed then we're going to show recommended articles based on number of views we're going to show top categories by their latest posts we will add search field for posts and categories in admin panel we're going to fix and improve multiple minor things comments on the post s Implement Global search on the website and maybe deploy a project on production environment with custom domain don't tell anyone and maybe you don't want to subscribe because you're constantly checking my YouTube channel if I uploaded any new video alright no further Ado let's jump into the video now let's start working on user registration and logging and for this we're going to use laravel Breeze uh you can have a look at the lateral Breeze documentation is pretty straightforward to install that I'm going to have the documentation always opened and even though I know what comments I should type it's always you're going to always make much less mistakes when you actually copy these and like don't have a typo when you're typing okay so I'm gonna um actually first we're gonna start the server vendor being sale up then we're gonna go inside the container Bender actually I'm going to exit this stop that and I'm going to start my application in a detached mode so vendor Bean sale app testing okay containers have been started now let's access the container when you're being sale Bash and now from inside that container we're going to execute composer require lateral Breeze Dev okay that was installed then we're gonna execute uh PHP artisan Breeze column install that will ask whether which stack we want to install so we are not using view or reactor API in this case so I'm going to provide the zero right here whether we want to install Dark mode support I'm going to provide no right here if we want tests no right here as well and we have an error and that error was expected because lateral Breeze is intended to be installed as a very first thing after you create your level application so it expects welcome blade PHP to exist on the reviews folder which doesn't exist so that's why we have this problem now I'm going to open resources views and simply I'm going to copy and paste homeblade and call this welcome blade PHP so I'm not going to use this welcome blade but I am simply creating this because lateral Breeze needs that and then later when lateral Breeze installs I'm going to adjust the content and create and maybe modify a few views and so on okay before we execute lateral Breeze one like a disclaimer lateral Breeze will modify your views and layouts and few other things so make sure you have everything picked up like for example and my recommended way to backup everything is using git so use version control system and comment everything before you run lateral Breeze in this case because as I mentioned It's Gonna Change many things in your project okay I have everything commented I'm Not Afraid about losing anything so I'm going to execute please insta zero no and no now let's wait few seconds Breeze was installed then it run npm install and npm run the npm Run build we're going to execute npm run Dev by ourselves and now let's have a look so here's our application and let's access to the main page and we have undefined variable posts and that comes from welcome blade okay welcome blade was used by laravel Breeze automatically now let's open web.php which is our main roads file and right here everything was modified by lateral priests so this like a CN color line indicates that I have changes that uh changes come from version control system so basically if I click this I see what was my previous version so I'm going to copy this part and at the very very bottom I'm going to put that so my roads and also at the top these Imports have been changed I'm going to copy this and I need profile controller but I need my post controller inside controller as well so now in my web HP I have uh like modifications bilateral Breeze as well as my previous rows what I had before so small hint right here don't put these above because this is a very very generic route so it is matching all the everything if the previous rows didn't match so whenever you try to access a dashboard or profile or any other robe declared before this will match and it will it will use that so this needs to be at the very bottom if you don't believe me you can put this at the very top and you can just try to access like other pages and you will see an error okay I'm going to save these and let's modify a few things I don't need this uh welcome because I am using the post controller index and let's save this and have a look so we have this error that comes from navigation blade navigation blade is something also introduced by Laurel Breeze and let's go in The Roots resources Fields views layouts and right here we have this up plate and right here like almost every line was changed by lateral Breeze I want to recover my previous layout but I need few things from here like for example white scripts CSS and javascripts which I want to put in my layout and maybe also later we can move our header into layouts navigation and so on so I'm going to copy everything and create new temporary file like scratch file and I'm going to paste everything right here and I'm going to revert everything using version control system if you had up late PHP picked up then you can easily revert that so I'm gonna select everything and type a control alt and Z on my keyboard and it's gonna that's going to revert everything inside this file I save this rule of the page and we have another problem and that comes from the layout again but that happens because the component was changed the layout component if we go in the app view app layout right here a few things have been completely removed like the Constructor was removed so I'm going to revert that so I need this and also Imports have been removed I'm going to revert this as well so now I save this and reload the page Nic application working right so I can navigate between pages and that was completely fine however if I try to access like login for example we don't have styles at all so how we're going to do that now let's open the scritch file and I'm going to copy these white tag and let's open up blade scroll up and I'm going to put this uh before closing headtech like this this actually these resources app.js if we have a look uh let's go under resources JS and app.js this uses Alpine this Imports Alpine so we have already Alpine and we can remove this JavaScript from CDN if we open these app CSS this uses Talon CSS so we can completely remove these Talon CSS from CDN which is fine great now if we save this and reload we see our Styles in JavaScript is completely broken and that as I figured out is kind of bag of laravel sale in white combination of together if I try to access any URL these styles are not there if I open developer tools and expand that reload we see that error address is invalid now let's go in the white config it is in the root of the project and right here at the very top we're going to add server we're going to provide HMR and we're going to provide host to be localhost you should provide right here whatever is the domain your local domain okay so I'm going to save that and now if I reload these it's going to take a few seconds but now we see that the styles are big and we can navigate and we see everything is okay and we can also try to access login page and styles are there now this login page doesn't have header and footer which is something I want my blog to have my the login page of my blog to have also um the forward password as well as the registration all of them needs to have this header and footer those files are defined by lateral Breeze and they are available under resources views all folder and if we have a look all of those files have the layouts the main component they are using is the guest layout and if we open now guest layout there are obviously no header in footer and this is the guest layout and this is something I want to modify so that header and footer to be there so this is a layout but I'm going to actually change this slightly I'm going to remove this body and head completely let's remove this HTML as well and this right now is a guest layout but I want this to extend X up layout okay now let's format the code and now whenever the login form is rendered here's the login form it has this HTML included which on its own is extending the app layout okay we probably we probably don't need everything maybe we don't need logo we can remove that mean h screen maybe this is something we can remove as well and that's more like it there is probably some kind of padding padding top and we can remove that PG gray maybe we can remove it save okay that's much better and I want this form to be in the center so we have this justify Center but we have this uh under above small screens which we don't need we wanted this to be always in the center and we have with full maybe we can remove this with full and Max with medium margin top padding let's remove all that and have a look okay we need paddings we need padding how to put this in the center let's remove this w okay now let's inspect this and have a look so this is the this is the form this is the container okay the container which I see so the container comes from the app layout and if we open up layout and find where the main content is injected right here and if we just provide right here justify Center Maybe justify justify Center then the full form will go in the center or maybe we can undo these and open this guest blade and give this one w ool always and then this one already has justify Center okay I think that's better like making a change in the up blade is kind of okay but because the upload is used on other Pages as well it's not 100 correct to make change right here instead making changes in the guest blade will be much more safe we are sure that we aren't going to break home or any other pages okay that's perfect now every out page is in the layout I don't actually like the width of the forms so maybe we can do something Max with instead of MD maybe we can provide LG we need to wait uh okay it didn't work for some reason that has Max with LG let's provide Excel okay it has Max width but maybe we want to Define like a width or Min width as well or maybe this is even fine like not big deal so we have uh enough width for each individual field right I cannot I access login here I have the login okay so now let's try to log in and let's take here also putting the login and registration buttons in my profile buttons in the navigation as well okay if I try to log in right now I'm logged in this redirects me to the dashboard which is uh something we don't we don't have at the moment we don't have dashboard so probably we don't need that at the moment so for now I'm gonna simply remove this redirect to dashboard and that was basically modified in the road service provider right here that home was changed into dashboard and I went actually uh revert this into home again and now I cannot log I cannot log out because I don't have logout link okay let's actually take care of the putting proper links in the navigation right let's open navigation blade PHP and let's have a look we have couple of links primer navigation menu uh we have this navigation links which goes to dashboard and activates that right here it displays the user information who is actually authorized at the moment and I think that drop down is something we might need and we also need we also need logout like we have this here okay if we pay attention this is a responsive settings option so that is visible for mobile that is visible for mobile and the above one is visible for um for a desktop right but where is the actual login and sign up where's that here's the log out let's search for a login we don't have this here we don't have probably this in the guest layout probably it was in the up blade which should be a scratch file now here it is so I have the scratch file and there was a header okay that was coming probably from there anyway let's go in our up blade and we have the following navigation links and let me actually take one of the links and put them like this okay that should be login we're going to adjust CSS a little bit later this is register let's provide proper tests uh texts register and this is logging so we save and we see login and register however they should not be visible if the user is already authenticated because right now it redirects us to home which is also not correct and if we open this road service provider wrote a service provider and if we simply change this home into slash that will be more accurate clicking redirects us to home page we need to hide login load login and registration with user is already authorized so let's use auth a directive and alph that should be not Alf to be honest so let's do like this if the user is authorized we're going to display the my profile section then we're going to have else and we're going to display this so if I save now we don't see a login and registration which is perfect now if we open navigation blade here we have this settings drop down which is again for desktop the second one is for Mobile in this case let's make it simple we haven't done any changes regarding making our blog responsive so simply I'm going to take this part and go in the upblade and paste this right here I'm doing this only for desktop at the moment let's remove this hidden and let's give it display Flex let's save it have a look okay we have this drop down uh the profile is available and the logout will probably work perfect so now we have login and register I click on login click on register both working let's log in again and we have this my profile these styles of this my profile of course is not nice it should be probably in the styles of this so let's give it some small let's take the following classes and maybe modify this part yeah there are a lot of classes so let's paste this and have a look um okay let's give it legs paint items Center okay that's good let's leave it as it is right now or maybe we can put this navigation on the left side and these on the right side so what I'm going to do is we have this widthful and container and it has flex and it has Flex column as well but those are for mobile okay on above small screens we have Flex row item Center we don't want justify Center let's give it a justify between and now let's put those links in a div and those will be in another div like this now if I say that let's collapse this part if I say that this is how it looks like okay so we have this main navigation on the left side we have this user related navigation on the right side if I log out I see login and registration right here okay that's I think that looks much better okay now we have the differentiation between the normal navigation and the user related navigations in ideal case this register button even needs to be probably kind of Blue by default so why don't we make this blue and let's give it also text White like this so this is already like it's try it's takes our attention and we want to click that in register uh immediately right okay so this is what we're we're doing right now now let's have a look all the files that have been modified right now and I'm gonna use git for this so road service provider was changed into slash that's fine up CSS app Javascript was modifying that's fine Apple blade was modifying modified that's also fine now I don't want to these styles to be inside the layout so I will open that layout take this out from here and open this up CSS and paste them here okay so I want them to be inside CSS not inside HTML let's continue this is the app play that was modified we have this welcome blade which we don't need at all so that was created because of lateral breeze so I can delete this welcome blade and nothing will be broken I hope so if something was broken we're gonna of course fix and we we need to fix that okay then inside the web uh webphp those are the modifications that have been made that's fine we have the dashboard wrote um which which we probably need maybe we will need this later but at the moment it is not necessary okay let's leave this right now let's leave it it doesn't hurt then we have this composer Json which is the um which will have just lateral Breeze the white config and down below all the new files that have been generated by lateral Breeze like the controllers and we're going to have request files and components as well as the views and we also have some profile partials and layouts and test files okay so I don't see anything suspicious right here so I will be happy to comment those changes and make it available just um I'm gonna have a look at the final check we need to register and we need to also verify our email address if that is something which comes with a lateral Breeze if we open user PHP um okay if you open user PHP we must Implement an interface must verify Master verify email okay if we don't implement this interface whenever user registers his email is automatically verified and he will be able she will be able to access the system without email verification this is something uh which should be avoided and that's why I'm going to implement must verify email and now if I try to try to register let's use a seven-time email mailriate example.com let's provide some secure password so in it okay let's hit the enter okay it looks like we are actually authorized and we're in the system but okay this is this is tricky if we try to access dashboard right now let's have a look look at this thanks for signing up before getting started could you verify your email address by clicking on the link we just emailed to you if you didn't receive blah blah blah okay so we are actually authorized but we are not verified that's why the I'm going to close every tab and now I'm going to open Weber PHP uh because we are using verified middleware right here uh we aren't able to access the dashboard but we are able to access profile and we are able to update our password or delete the account and we are able to access the home page we are able to do basically everything which is kind of correct we don't do anything suspicious that requires email verification at this stage but if we are now for example do some action such as maybe leaving a comment on the article or upvoting an article we need to verify we need to be verified to do this type of action okay that's why maybe we can leave this as this right now but we should have received email verification which we need to verify I'm going to open now test email client which will be defined as a service in the docker composer yml and right here we see this mailpeat and which has which is exposed on the following Port 8025 so if we open our browser and access localhost port 8025 here we are going to see the client which is a local client for every kind of email and as we see nine minutes ago we received the following email and this is the email when we click on these we can verify in this is why I love working with Docker in general because you can set up all your services in a single Docker compose yml and test email ascending and database and everything in a single Docker compost yml and you don't need to worry about setting up all your clients and environments right hey okay if we have a look again the problem or the problem but the fact is that we our email is not verified now I click on this verify email address you are logged in I'm on the dashboard now I am verified and from now on I'm going to use this client whether I want to recover password or producer is not the user I can use this client and I will receive every kind of emails right here and now if I reload this page even if I try to access the page verify email I'm redirected on the home page because this is the default Road at the moment the problem I see here is that Mary can actually access to admin panel as well which is not correct Mary is a regular user what she should be able is to probably leave a comment on article upvote download but she should not be able to access to admin panel unless we Define it so but I'm going to Define it not like this I want only admin users to be able to access and they will be managing all kind of content and regular users will be able to just comment upload download and do things like that so we should restrict that and to do so I'm going to introduce permissions package from Speedy so let's search for T permissions and the very first link from spity.d.be domain will be the permissions package let's click on the installation that's a very powerful package so let's scroll down below and find the installation section we're just going to run composer require first and then this will be automatically done we don't need to do this we need to publish the config as well as the migration file we're going to execute that and we can clear the cache and finally we're going to execute PHP Artisan migrate okay then we're gonna do a few other things like uh uh entity has roles and probably defined roles as well but let's start from the very first step what we need to do right here like the prerequisites and everything is okay we satisfy those and now let's open the terminal so in the terminal I'm actually writing npm run Dev so I'm going to open second terminal and I'm going to log in inside the container vendor Bean sale Bash and now I am in the container and I'm going to execute composer require let me copy the Second Step which will be PHP Artisan vendor publish let's copy this and their required was installed let's now run PHP Artisan vendor publish those two files have been published permissions PHP inside the config and the migration file you can have a look at the migrations what is going on if you are interested you can find this in the database migrations right here and you will see that this creates couple of tables and this is the basically the whole migration which you can explore if you're interested okay now let's apply PHP Artisan optimize clear and it was cleared then PHP Artisan migrate all right if we have a look in the database schemas you can access to the database client uh through the um to the MySQL which is actually running in the docker and I'm going to check right now the database in the page performs database client just refresh this keymind we see a couple of tables like roles model has permissions module has roles and so on okay so those tables we are created now I'm going to open user.php and I'm going to introduce a new trade right here has roles it comes from Speedy permission trades has Rose and now I'm going to actually Implement an interface so basically regarding permissions we did most of the things let me try to do one additional thing to create the role actual role so the we have the database Cedar right here uh and actually I'm gonna check what users we have we have uh zura and Mary and I'm going to create now admin user okay and I'm going to Define also admin role as well I'm going to comment this post Creation in the database theater I don't want to create posts that was just for testing purposes in the first part and by the way if you haven't checked the first part first I recommend to check check it and then continue watch the second part and then now let's create a user so let's call this admin user that will be user Factory let's import the user app modules user right user Factory create let's provide right here email will be admin at example.com let's provide name it will be admin and let's provide password that will be back Crypt it's provided admin123 okay that's the password and now let's create admin role as well that will be role and that will be spotty permission models create and we have to provide a name of the role that will be admin so the role is actually created and then on admin user I'm gonna call assign role so this assign role method is not seen by Page performing it does not autocomplete but this assigned role comes from the trade we added on the user model so if we just Define an annotation right here that the admin user variable is actually an instance of app models user then when we try to call assign role page question sees that and we can provide right here admin role variable and whenever the CD is executed it's going to create the user create the role and then assign the role to that user so let's bring up the terminal and I'm going to execute PHP Artisan nanometrate DB colon seed so seating database has been completed let's now open database then we have new admin user if we open roles we have admin role and if we check model has roles we're going to see that the model ID which is the currently added 11 ID user has role id1 okay so we defined those roles which is perfect now let's try to basically log in with the new user adminate example.com and let's let's just reload the page sign out and now I'm going to use admin at example.com admin123 and look at this so we are right now logged in as an admin user but actually if I try to log in with Mary let's use the auto compilation now we are still in the admin so we created role we created admin user but we haven't defined a restriction for normal users to the admin for this again we are going to open the user PHP and we're going to implement right here an interface called uh filament how is it called I just forgot filament user I think that's it filament user yes and we have a red underline right here this uh it comes from the PHP showroom it indicates that we need to implement a method from the straight so if we just hit the control and mouse on this filament user we see that it has the following following method defined and that is can access filament in phpstorm I can just hit alt and enter and this gives me a couple of options Aid method is tabs click OK and at the very bottom we're going to see this method can access filament and we're going to return true or false from here if I just return true basically every user will be able to access if I return false none of the users will be able to access so if I just reload now Mary is not be able to access even admin will not be able so we need some kind of condition right here okay so this has role we're going to call a method has roll excuse me has a role and specify the role name so only those users should be able to access that interface if the user basically has that specific role admin role in this case so if I just roll the page we are not able to access this so I'm going to inspect because I want to clear the session I'm going to go in the application uh cookies and I'm going to clear everything just reload the page and it redirects us to the login and we try to basically again let me actually try to log in with Mary we see permission forbidden but if I try to reload the website we are actually logged in with Mary and I can log out from here as well okay let me reload the page and now let's try to access with admin user admin hit the enter now we are able to access filament admin admin panel which is awesome so the admin users can create categories posts text Regis manage the content and normal users can log in on the website we haven't defined any any functionality which is relevant for the normal users which are optimized on the website but still we have the authentication implemented which is which is great here I have generated users resource so from admin I can manage users as well I think this is uh generated outside of the recording so you cannot find this actually in the first part but generating users resource is pretty identical generating post resource so I just did this because I needed users in the admin as well but the most important thing right here is that every user which is created right now from admin needs to have admin role okay if I just create new user it will not have admin role and this is something we are going to change so I'm going to go in the app filament and let's open user resource and open this create user right here and we have to customize this we have to add a new admin role to every user when that is actually created so right here I'm going to create create new function handle record creation which is a protected function and we can actually customize this this handle record creation if we just fold the follow this it gets the model based on the class and creates that so whenever this is called we can take these as already created user and say that in a very table right and we know that every user has that has that trait as roles so basically if I let's call in the create user so if I call on that user hold on if I call this a sign role again after completion doesn't work because PHP stream doesn't understand that this user is an instance of app modules user so I generally tend to Define this because I love when people store autocomposite for me it's also very easy if you want to search then in your entire project where are the instances of that user basically it will find that place as well if I just remove The annotation and go in the user PHP and right click on the class and try to find the usages of that class it will not find that specific alone that specific variable because it has no idea that this is an instance of app models user right if I add this annotation and then call this find usages then it will find end it's also good if you want to find out where you have all the instances of the specific specific model so in this case I'm going to try to call assign role on that and provide admin uh admin right here and finally we need to return user my keyboard I just don't like my keyboard I'm going to replace it okay so the user creation process is like this and if I now go in the admin and try to create new uh new user so let's call this shown let's give it Sean at example.com email verify that is something we can Skip and the password will be something secure okay and let's hit create uh let's hit never okay so the user was created now the most important thing is to go in the database check the database let's open users first we see that John is created with ID 12. and second is the model has rows let's open this and now we see that there is a rule one assigned to Model 12 okay however I think the user might not be able to log in because email verified is actually null and this is something we probably need to also fix let me actually try to sign out and try to log in with John yes I am not able to to log in now let's open users and I'm gonna let's actually try to log in with admin admin123 okay good let's open users and we can edit this and provide uh provide some some value inside email verified it and whenever we do this this password is by the way required so this form is just a very very basic form I just generated as I mentioned outside of the recording I haven't customized that at all the password should not be required whenever we are updating the user password should be optional and even we should have probably two fields for the password password and password repeat so that if you want to change a password reset the password for a specific user you should be able to uh provide it you should provide it twice just to avoid any kind of mistakes so in this case for Simplicity I'm just going to provide from one to um from one two like whatever and hit save changes okay that was saved but now whenever we try to create new user this email verify that needs to be set automatically okay so let's customize this form and let's go in the where's that create user I know that is our resources user resource create where is the form down below here we see user resource okay and so this is the form uh we can completely remove this email verify that we don't need to provide this twice uh sorry we don't need to provide this at all we need to provide password probably twice let's remove required from here as well we can provide right here the method using which we can hide the password field when we are editing the user as well so like the password the input field is the password max length and let's provide right here that should be hidden on edit so we don't want this to be on edit however we can also provide that this needs to be visible visible on create so in this case we need to Define probably two password Fields let's do like this so the one password with the password max length this is hidden on edit let's select this and the second one is visible on Create and we can also specify right here required okay so that must be required and that is visible on create let's save this and have a look reload the page this is user creation so we see password actually twice which is something we shouldn't see uh let's hide this on create as well okay let's try to have this all in a single input field password required not the required a max length and then let's just provide hidden on edit and then provide required and visible oncreate let's see if this gives us exactly what we want okay the password is still visible on user creation that's correct so it should be visible on user creation but the interesting thing is update so if I click update we don't see password Here we choose which is exactly what we wanted in this case however as I mentioned if you want to reset the user password you won't be actually be able to do this so in this case I'm going to add one more method and that will be confirmed so the password needs to be confirmed and we need a second field for password confirmation as well and let's give it the proper name confirmation all right and the password confirmation also needs to be visible on let's actually take this part so it's a password max length hidden on edit required visible on create blah blah let's now reload the page on edit we don't see that uh let's that was actually View I want to submit this form just make sure that even though we just we don't display it it is not required we have this required function here so click on save that was actually saved perfect uh if we go in the users we see John 2 that was updated now a new we have password and password confirmation let's create Tom for example we provide password if I don't provide the password confirmation and hit create we get this error if I provide incorrect password click create we get this error perfect so now we have possibility to we have possibility to set the password of the user okay did I make any mistake let's provide password properly password confirmation field doesn't okay that looks like we don't have it as we should have so the password is password max length in required and it is confirmed password confirmation okay great again let's provide password hit create it doesn't seem to be working okay let's check the source code and I think that is the problem it's a stupid mistake so password confirmation obviously doesn't need confirmed role the confirmed rule is necessary on the password itself so if I save this and hit create now the user was created so that's perfect however speaking of the email verify that that is still null for every new user so let's just open that create user and maybe before before the user is created inside the data we can provide email verified it is just current time let's provide time here or I think we can provide carbon now as well so I save this now let's try to add new user Let It Be Gene in this case and gym and let's provide password at the end okay password confirmation does not match hit create okay email verify that was not saved okay we can we can create another method which just like we did in the post resource if we open these post resource here note here sorry right here in this post resource we have these create post and we have this mutated form data before create okay so we just copy this and go in the create user and let me paste this here and mutate form data before create we provide email verify that and let's provide carbon now let's remove this from here I save it and let's try to add new user let's give it test in this case let's give it short password click create okay email verified it is still and not provided and I think the reason might be that this is excluded and not provided in the fillable and that is added in the casts so we need to add this in the fillable and then it will work let's try to add new user S2 let's provide short password click create and this worked this time so now we have this test user which has even verified it and this is admin user by the way and if I now try to sign out and try to log in with the test two let's try to log in first with the test it doesn't work because the email is not verified but now if I try to log in with test2 okay it doesn't work either and I think the reason might be that the password is it saved properly let's check this not sure the passwords are saved and passwords are saved as plain text obviously we haven't implemented this part so if we open user resource uh not the user resource but create user and right here mutate form data before create so we want to hash the password before create so we're going to call Big creeped here and then we provide a data password just like this now let's create test three in this case we need to log in with admin please try again three seconds okay one two three now let's go in users and let's create and by the way that was an extra security of filament which I liked so if you try too many attempts incorrect attempts then it tells you to wait that's I think really good let's create now one more user in this case the password encryption should work hit create okay it doesn't work let's give it short password okay so we have that now let's check the database first okay here we see encrypted password now let's sign out and try to sign in and that works this time okay now every user which is Created from filament admin is an admin user and the password the email is verified and password is encrypted and I guess we can delete all the previous users because their passwords are not encrypted okay now I'm going to implement one very important and really cool feature and there's going to be upvote and download of Articles every authorized user will have this ability to click a button and upvote article and give a credit to the article and in the future maybe based on the number of apples on certain article we can promote that and show on the home page or showing recommended articles and do some things like that so let's start implementing this really cool feature and I'm going to do this using laravel Live Wire uh filament PHP behind actually is using whatever Live Wire but we haven't used on the front end it at all so I'm going to open the documentation a live wire and let's have a look so let's go in the docs and I'm gonna like um give you a quick overview so right here you can find the documentation let's click on install Live Wire we need to run composer require but as I mentioned because we already have a filament PHP which internally uses a lot of a live wire we can skip that section and we can just import that live wire Styles and scripts in our layout just to make sure we have Live Wire installed let's open our project let's open composer composer log file and inside there let's search for Livewire and if we see that in somewhere as a dependency it means that it is included and if we see if we check the package uh that is Livewire late rate limiter and the live wires dependency of it and if we just follow that and find out internally it's going to be finally a dependency of filament PHP okay so we already have Live Wire installed now we need to register Styles and scripts in our application so I'm going to open layout up blade PHP and in the header let's do this before white let's include the Styles and at the very bottom they are like a before the closing of the body tag I'm going to include Live Wire Scripts okay so far so good and then having a look at the quick start we can already generate a component so in this case I'm going to call my component let's start a new terminal vendor being sale Bash all right and now let's generate a live wire component and I'm going to call this upfold download component okay that's going to be like your two buttons uh hands up thumbs up and thumbs down and yeah just like this we're going to show number of upvotes in number of down rules on a particular article so let's click enter right here right so it asks me whether I want to start the Ripple or not I have actually already started it so I'm going to type a no right here so the Live Wire component was actually generated and if we open up HTTP Live Wire we see this apple download there's a very basic Live Wire component and it renders the following view file and that view file already exists upvote Dash download play there's an empty blade file okay so we have this Live Wire component but now let's focus on the database right so we need the uh actually before we do the database let's put some something right here like a test and then let's open view file there's going to be the article interview and inside that inside that white background card at the very bottom maybe we can use Live Wire colon and the component name in this case it's going to be upfold down vote that's going to be the component all right so I save this I think we need Dash right here upload Dash download so I save this and now let's open the front-end side and click on the very first article we are in the inner page then right here we see test okay so the Live Wire component is actually rendered from here now let's focus on the database because we're going to save this app volts and downloads in the database I'm going to generate new model and migration HP artisan make model upvote download let's call this same name as the component and dash M we need this as well now let's open migration file right here and let's define few Fields like first I'm going to define a Boolean type of field and it's going to be ease upvote okay so if this will be true it means that user hit the upvote button if this will be false it means user hit the download button at the same time user cannot hit upvote and download buttons on the same article so it's going to be either port or download so this is how I'm gonna do this and we'll also provide right here two foreign IDs uh one will be post ID on which post the upvote or download happens that references to ID on table hosts and we can also specify um own delete what should happen on delete uh Cascade let's provide Cascade here I'm going to duplicate this same line and it will also provide the user ID who made this upfold or download the table will be users and we can leave this Cascade so it is as simple as that migration migration excuse me is ready now let's open Terminal and execute PHP Artisan migrate okay the migration was applied and if we check the database we are going to see down below upload downloads table perfect let's open up vote download uh we need model upvote download and inside fillable let's add those three Fields is up fold we need post ID and we need user ID all right so far so good now let's open this upload download Livewire component and in the render we are going to select how many apples and how many downloads these particular article has but we don't have any identifier for this particular article so what we are going to do uh this upper blade I think we can close this I'm going to close Ian as well I will only leave those files which is relevant for me at the moment I'm going to close the migration as well inside the view so from here I'm going to provide post so that's going to be the actual post on which we're going to show up for it and download we're going to accept that post variable inside the Live Wire component like here we're going to create a mount function in the mount function will accept this post first we need to import this post model here then I'm going to create uh oblique host variable and public and then this host will be given post all right and now here inside render I have access to this post and I can select how many upvotes or downloads these post has but let's uh first to the front-end side and I'm going to now open hero icons which is a like SVG icons really easy to use we're just gonna look for thumbs up or something like this here we have those two icons and we just need svgs there's like a no need to install or require any CSS or anything we just can copy SVG files and let's open this up for download and I'm going to create two buttons and that's going to be for upvote so I'm going to paste this here and the second button will be for download let's copy SVG and paste this here all right so that's perfect now let's add couple of CSS classes to those buttons as well so we're going to give it display flex and items same term I'm going to give it also Gap two uh and let's give it also on Hover the text should be text blue like a 500 and let's give it also a transition all to have this nice effect on Mouse over and right here and here we are going to Output two variables number of upvotes and number of downvotes down below we need down volts and we need to pass these two variables from the Live Wire component into blade file so I think we don't need this model I'm going to close that and let's open the component and there are two ways to pass data from Live Wire component to Blade file one is to declare that variable as a public property of the class and then can this can be accessed inside the blade file in this case if we want to access post we can access easily from these view blade file the second approach is to pass these two variables in a view so this is what I'm gonna do and I like second approach because whenever something is changed in a component like even Handler is triggered or some sort of data is updated then this render method is called and the if we select some kind of data then the view also will be called and view will be updated very easily okay so now let's select up folds and that's going to be Apple download from modal we're going to run where host ID equals to this host ID and we are going to we're going to add another weird where is upvote equals one or true and finally we're going to call count okay so this will be number of upfolds uh that has been made on that particular post uh we can move this where and count down to make it like more readable so I'm going to duplicate this and the second one will be downloads and right here we're going to provide false number of downwards on that particular article okay so that's perfect now let's provide right here compact up Folds and downloads now I'm Gonna Save this and let's test this so far let's open the front and side and we have our basically let's reload okay there is gone and at the very bottom we have these two buttons with a zero okay let's give small CSS classes here let's give it flex and gap of two okay perfect we have up folding download the how over effect works as well now let's Implement actually clicking on that button let's call the inner component and I'm going to create a component sorry I'm going to create a method let's call this upfold download okay so this method will be called whenever user clicks on app Vote or on download and actually I'm going to accept a parameter right here whether this is an upfold or download so why I'm doing this as a single method and not two separate methods like up fold is a separate method in download as a separate method because we're going to have very similar logic in those both methods if we're going to do it separately and I don't like code duplication so that's why I prefer to write a dry code and just give a parameter right here okay and calling this up for download method from the component from the blade file will be super easy we just provide right here wire colon uh Clique that's the event name and upvote download and then we can provide the argument okay by default the argument is true so we can provide only false right here if we don't want it to be upvote if we want it to be download right so so far so good but in order to upvote or download to happen the user needs to be authorized right so we can check if the user is authorized Android direct to login page but first i'm going to actually get the user because if the user is authorized I need to access the user information in any case so I'm going to call request user so I'm going to get the current user and I'm going to add also annotation this is an instance of app modules user because uh like I really like to do this in terms of I need some kind of Auto completion or things like that then this works excellent so if the user does not exist we are going to Simply return from here and let's call this redirect we're going to redirect user to a login login page okay however if the user exists there is one additional check to do if the email is verified for that user okay and this is the case where Auto completion works perfectly because I added the sanitation right here so if the user has a verified email here more more correctly if the user doesn't have a verified email we are going to return hold on return these redirect oops and in this case I'm going to provide the road function and pass the actual Road name where the redirect user to the um like email verification page and if we open now out PHP from the roles which is generated by lateral Breeze and scroll down below we should see this verify email URL with verification notice name Road name so this is the road name we're going to use in this case so I'm going to provide it right here okay so and at the very bottom it means that the user is successfully authenticated on the website and the email also is verified so now we are going to Simply um make a record in the database or if the record already exists we're going to delete that record so first let's select if there already exists Apple download record uh in the database so let's select upvote download equals that's going to be from the model let's write weird for that specific post post ID underscore ID equals to this host ID okay we need another where in this case we're going to provide user ID we are interested if there is upvote or download for that specific user these are not this in this case we just need user ID okay so we select that and we just need to get our first record from here now if this does not exist there's no upvote download record then we're going to do the following so we're going to create new record upload download create and we are going to pass is up Folds excuse me is up fold will be the given parameter whether we are doing upvote or download we're going to provide post ID this host ID and we're going to provide user ID as well user ID okay that's perfect and I think we can return and don't continue anything below from here then if the app will download already exists we're gonna do two things like if the user is clicking upload button then we're going to check if the record which exists in the database is for up fault we are going to delete that record completely okay so let's check if the action what we're going to do is upvote and the record up for download maybe that's a confusing let's call this model okay I'm going to rename this and call this model that's a database model if the model in the database has is upvote so if we are doing upvote but in the database there is already up for type of record simply we are going to delete the model okay it means that user wants to remove his app vote simply take back his upvote we're going to do an else statement as well if this is not the case uh then uh okay let me first do another if right here and then we can the the else case will be very straightforward okay so if user is doing upload in the model um already has upload we delete that or there's another case if the user wants download and model already has download is upvote equals false okay in this case we do the same thing like if the user has previously hit the download button and let's call it dislike this is I think very easy to say so if the user previously disliked the article it now wants to remove the dislike then we delete that so in this case we have model and in model we specify is upvote equals whatever is given upload okay so this is what we are going to do and then on model we are going to call Save so this will update the existing upvote download record and whenever this is executed this function is executed and because this makes some like modifications in the database as well the re-render method will be executed and the the selects will run and the counts of each of the items will be already modified so if you don't believe me let's reload the page and click upvote and as you see right here we see one if I just roll the page one is there so record was successfully made in the database now if I click upvote again it removes the upfold and now we see Zero again now let's click download we see Zero click download again sorry we saw one and now we see Zero now if I click up vote and then I click download then look at this so it actually worked properly it changed existing upload record into download so I think that works excellent and that works exactly as I want except that I'm going to add one additional thing if the currently authorized user has this particular article upvoted we're going to show this button blue so we're going to do this in the render method and I'm going to Define a variable here has upvote and I'm gonna also add a comment right here which perfectly describes what this variable should do so that's going to be the status whether the current user has upvoted the post uh or not and this might be now true or false if it's null it means that user has not taken any action has not upvoted or downvoted that article if it's a true user upvoted if it's false user downloaded that particular article okay I'm going to query also a user let me actually grab this from here I need the current user and I'm going to make a query in the database first I'm going to check if the user is authorized if that exists then let's actually select a variable from the up for download we can call this model or current status let's call this model okay model equals upvote download where provide post ID equals this host ID and we also provide the user ID user ID and we just select the very first record all right let's move this where in first down so we select the very first item for this particular user and the um for this particular post and now we're gonna check if the model exists so if there's a adap photo download for that specific model then his upvote basically equals whatever is the models is upvote okay but I'm going to add right here double exclamation just because this is up fold will return true uh not true uh it will return one or zero because the database will hold the values into one and zero for Boolean mySQL database and using this double exclamation we're converting this into an actual Boolean and now in this view we can pass his upvote and now let's open this upvote download blade PHP and I'm going to add CSS classes so first right here his upfruit if that has upfold exists so if if it's a chewable value so it will internally be true actually if this is true then uh we don't need actually hover anymore but we can leave that but we're going to directly make the color blue 500 right so let's do like this and in else simply we don't add anything let's make on however it uh like a 600 let's do like this and in the downward button we do the same thing very similar thing however if the upvote equals false okay I don't want to type if not upvote because that's tricky null is also not has upvote so if the hazard for this null then this will be also satisfied that's why I want to explicitly check if it has upvote is equals false with three equality because right here we're going to have false so in this case I add the text blue 500 right here otherwise we had an empty class let's change this into 600 let's save this reload the page and voila we see this upfold pattern blue if I Mouse over it slightly changes the color because it's uh now on Hover we have 600. if I click on the download then this button becomes blue so that's a perfect indicator for me as a user that I have once upvoted that particular article which is which is awesome now I'm going to do one small fix so right here we don't see the previous pattern but actually if we click next and keep clicking next finally we're going to reach the end where there are no more articles and in this case there will be a problem so in this view blade we check if the previous exists then we render the previous button and if it doesn't exist simply this is not rendered however we don't do the same check for the next button so as simple as that like let's copy this if statement and change this prev into next and then right here we need end if so we format the code and if the next exists we render that if it doesn't exist we don't render that and it's as simple as that now let's start working to save views for each article whenever user opens an article we're going to save that and probably also save a user ID maybe IP addresses as well as the user agent so we have a little bit of information from which location users are checking our posts as well as from which browsers they're actually doing this so it's going to be good good to save so we're going to create migration save post views and then in the admin panel we're going to display for each article how many views that article gets and later we can also Implement to sort the top particles or posts by their number of views right so I think it's going to be pretty interesting so I'm going to open phpstorm first I'm going to bring up the terminal and I'm going to create migration PHP artisan make I'm going to create model post to view and I'm going to generate migration as well now let's open create post migration not this one but create post create post views actually so we need to Define two columns right here so string uh one will be IP address and let's give it a length of 55. I'm going to Define also user agent let's give it a length of 205 I'm going to Define our foreign ID for post table according ID post ID that has constrained constrained on post table and I'm going to duplicate this basically right here in this constraint method you can specify the table name however if you don't specify it's gonna a lot of it will assume that there's a posts table based on the column name and we can specify here user ID as well but the user ID actually should be nullable because unauthorized users might also be checking articles right so I'm going to save these now let's open post view model and right here I'm going to define a fillable with these four columns so I'm gonna just copy them paste here let's save everything let's semicolon all right now we have modal and migration ready now I'm going to bring up the terminal and execute PHP Artisan migrate all right now we have this table ready and let's open post controller and we're going to check uh show method where we're going to see one specific post and right here we are going to maybe First Take request then down below from that request we are going to get currently authorized user and then we're gonna run host view create so we're going to create a postview record we're going to specify IP address and we're going to get these from request IP method we are going to specify user agent we get this from request user agent and we're going to specify also post ID which will be current post ID and user ID as well and that's going to be current a user but I'm going to use a question mark Arrow here because the user might be now and then specify ID right here so this will basically return null if the user is now and it's gonna it's not gonna throw an error so I save this and now let's open website and we are on specific article page and I'm just going to reload that page now let's check in the database in the post views table what do we have here so we have recorded and this is the API IP address and this is the IP of the docker container running and we have the user agent we have pulse ID user ID and dates of course if I try to log out or try to open the same article in incognito mode it's going to make a second record but right here we don't have user ID because we made this nullable and just like this we save like all the basic things we need about the user who is basically viewing the article and later we can suggest to the user based on its views which articles might be relevant for that user all right here's one additional uh thing which can be added into this application and I give you this as a challenge I'm not going to implement this in this video if I keep refreshing this page it's gonna make records in the post Fields table as many times you refresh all right and as a suggestion you can generate a random token and save this in the user's cookie and you can give this random token Associated a lifetime like one hour for example and you will assume that all views the specific user will make on this article in one hour will be considered as a single View and you are not going to make records in the post views table unless that one hour or whatever time period you specify the time period passes and that's good because if the user opens the article and for some reason decided to refresh it or just close and reopened it immediately so you're gonna make record multiple times okay you can assume that this is a single View but if the user checks that article like few hours later or like uh tomorrow then you can consider that this is a second View okay as I mentioned I'm not going to implement this but as a challenge I think it's really interesting and useful so I give this challenge to you and let me know in the comments section if any one of you will implement this challenge in this uh in this project all right I would love to know about this all right now we have that information it's time to bring that in the admin panel and display these probably above the um about this card to display number of views for that specific post also number of likes or the same as app folds and downloads because we have all that information in these like we just need to Output them okay to display that kind of information we need to create widgets in filament so I'm going to open filament PHP documentation and we can search for uh widgets somewhere let's search for widgets here we have that getting started okay so we need to create a widget we can specify also the resource and then we need to display that widget in the post view so let's start step by step so first I'm going to create the widget I'm going to copy this command and open uh PHP swarm I'm going to close everything let's bring up the terminal and execute uh phpr design make filament widget let's call this post uh post overview right okay we can specify your resource but I think we can leave this as it is right now uh let's hit the enter okay post overview was actually created let's open this widget post overview here we have it it also generated a blade file for that so we can open also post Dash overview which is the blade file Associated to that specific widget I'm going to type here hello from widget okay we created the widget but we are not using it yet let's go in the post view app filament resources and we have right here host resource inside there we have a view post and that view post has get a header get header widgets and inside that get header widgets we can check the appearing but it's returning an empty array so we can return our widget we should return our widget and that's going to be post overview widget class all right so now let's save this and open the admin panel and just reload the page and look at this so right here we see hello from widget so we are using already our widget I want this widget to be on full width by default it is um like uh with a half half size but I want this to be on full width and then create three inner cards um inside the actual blade so let me actually do this in this widget post overview I'm going to Define uh called column spun column spot we actually we can actually check what properties the parent class the widget class has so we have a couple of um a couple of properties right here one of them is called span and I'm going to specify the column spawn to be actually three okay so let's save these and reload and now we see this to be on a full full width and we need also some sort of a data which needs to be passed to the Views to check this impairment again so we see this parent widget basically is a pure Live Wire component as you can see it extends for Livewire component so it has somewhere render method it renders our view past View and it passes get a view data right so this get view data is empty at the moment but we can we can override that get a view data function and return the data we need to be passed to the Views so we need three main things to be positive views like a view count number of views that specific post has uh we are going to pass let's let me leave empty right now we're going to pass upvotes number of upvotes and we're going to pass down volts all right let's start implementing from view uh view count so from post view we are gonna write aware and when to specify post ID equals to some post ID and that post ID basically can be taken from the record of this widget because we are using this widget inside view post right here that view post is for one specific post and we can use record we can use this record here so not sure if this is declared right here record I think this is not declared but it is written in the documentation that we can access that this record This Record and then obviously we can take the ID I'm going to collapse the left side so I'm going to take ID from here and then let's execute count on that okay view count let's save this and check if this works so far so view count variable needs to be available in the post overview so hello from widget and let's output view count with dollar sign obviously so we save this and reload the page and let's have a look record uh property record not found on component let's check post overview all right this is because we need to also Define this record so that's going to be public model record to be null but we also need to specify here question mark because uh because this is now by default in the question mark is necessary here let's actually import the eloquent model here we have that and whenever we Define this now we should not have this error anymore now look at this now we have number of views on that specific post that is perfect okay in the same way let's do Up full downloads avoid download where we specify post ID equals This Record ID and we call also another we are is upvote equals one and finally we call count like this and let's let me grab this and simply we're going to change is upvote equals zero and let's change this into integer or true or false we can even use true or false or one or zero as integers so I save this now let's print those two variables as well number of upfolds here and number of down votes here so here we go let's reload the page we see one up vote and zero download if I go on post and click on download button instead and reload now we see Zero upvote and one download okay now it's time to Simply render this content nicely in this area I'm going to open displayed file and let's specify the main widget to have the following CSS classes like let's give it agreed and grid columns three and let's give it also get three okay inside there I'm gonna have three cards so I'm going to duplicate this three times and if I save this and have a look we already see nice three cards right with equal width and now let's define in the first one we need to display view count uh let's use also like H2 to actually Define what information we have this in this card like views and let's give it classes like text large um above small let's give it text extra large let's give it font bold let's give it uh tracking light the following classes and down below let's create one div inside there let's give this div Flex because I want to display icon as well and give two in between and now here we need the some kind of eye icon and then we need view count right so let's open now hero icons and let's grab I icon here and let's paste right here save this and have a look okay views and this is 19 number of views that's perfect now let's move on the second one and we already have this kind of template of the card so why don't we delete the other cards and simply duplicate this because we all have all the CSS and right here we need to display up folds we want to obviously change this SVG so we can look for thumbs up called psvg paste here that is up folds by the way that should be down volts the last one should be down volts and the other one should be upvotes and my copied SVG will be for up folds and let's also output the variable up folds here this is downloads and now let's copy SVG for downloads download votes I'm gonna format the code oops and here we have 1000 volts okay and here's the overview now we have three cards the first one displays views and this is the the whole card let's collapse this second displays up folds and here we have the variable for upvotes and the third one is for down volts perfect so if I save this and now reload admin panel we see views outputs and down volts and let's just click on thumbs up here and this one obviously changes okay I think that's perfect now let's make categories in posts searchable in the admin panel because if you have more posts it's going to be hard to find your desired post so let's open well it's open let's close everything and open um oh it's called the list we need to open pulse resource and here we have tables and forms information so we don't care about the form at the moment we care about the table and in this table I'm going to specify that the title is basically searchable field and whenever you do this in the admin panel you will see this search box right here and then we can search for JavaScript and here we go we can search for lorem and we don't find anything we can search for Alice and here we find all Alice keywords mentioned in the title and I think that's perfect now let's do the same thing on categories I'm going to open category resource let's scroll down below on the title and specify here searchable [Music] below the page and we see and we can search for laravel here we find it okay that's good it searches inside the title for categories as well as for posts however if you open posts and we want to search some text inside body as well let me edit this and in the body right here I'm gonna add like a zura keyword okay so if I save this and go in the post and then try to search zura I couldn't find that because this search is only inside title right if I specify zura in title obviously it's going to find but this is not what we want we want to search in the body as well we can specify to this searchable method array of attributes it needs to search in in this case we will specify title in body in this post resource so I save this and now if I type 0 right here it's going to find this because it searches now inside body as well I think that's awesome the searchable even has if we just click on this it has a couple of options right here you can even specify whether the search is for individual column or This Global search like if you specify here that this is for is is individual uh actually let me let me do like this is individual and we specify true here this means the following we are gonna see this individual search field in that specific column and we can obviously add additional searchable columns right here like a filter by status whether it's an active or not we can filter by publish date and so on okay in this case I'd rather to have a single search because I don't have that much cons right there so I'm going to specify searchable with the title in body and I can also specify sortable if I want so so if I just follow the page I see that the title is now sortable and then click on this and sort uh by the actual title and the sortable is I think very useful so we can specify this on publish that as well and maybe on active as well so if I save and reload we see that we can sort burst only deactivated posts and then actives one and if we click on the publish date we can do something similar right here I'm going to add this sortable to category Resource as well on title and probably on updated it as well now I'm going to add one useful thing to every post whether you're in a post inner page or in list as well and that's going to be estimated read time in a human readable format and also number of words for that article so that when you're looking through the blog website you immediately know if this is not too long probably you want to click it and just read it okay if it's like five minute two minutes article so I think that's that's really handy and useful feature so let's actually uh open uh post model I'm going to do this in post model and I'm going to create a custom attribute where's the post model here I have it okay let's close to the left side and maybe at the very bottom I'm going to create a public function human read time and that's going to return custom attribute from illuminate database eloquent class attributes so we'll return new attribute and we are going to Define only getter for this we get value and actual attribute here and now what do we need to return from here so we're going to return number of minutes to read that article that post as well as a number of words so let's start by counting number of words and that will be using Str facade uh okay so it's your helper we're going to execute words method here and actually we need to specify a word count and let's specify the body and it's going to be from attributes let's call this attributes in plural form from attributes to get the body but that body will contain HTML tags as well so let's run strip tags endbody okay so we have number of words how to define a reading minutes for that specific words like to take an estimate average number of words per minute it is about like a 200 words so we call sale method divide number of words on 200 and just like this we have minutes and then we're going to return from here minutes but we are going to also specify like a mean right here as a string but based on whether this means is a one or two we either need mean or means or like minutes whatever we decide so in this case I'm going to wrap the word mean and then specify that I want this to be converted into plural based on mints values and just like this we have number of means I'm going to leave a number of words unimplemented at the moment and let's open post item blade and probably here next to the get formatted date we are going to Output post and whatever is the name like human read time in a camel case we need to convert this into underscore format human 1 read time so I save this and reload the page and we see five means here five minutes here all of them probably will be five minutes except the first one this is just one mint right so that's excellent now let's go in the post and append right here number of words as well like comma and then words space let's wrap oops words in called plural on that on words here we go we format everything and reload the page and we see one minute 90 words like five minutes nine hundred something words okay and we'll see five minutes and on the others basically will have roughly the same number of words but if we edit the article which is created by us and simply copy let's remove the Zero by the way and copy and paste these multiple times and click save changes reload the page at the very top we see three minutes 200 450 words so this is it and we can output this information on the inner page as well so I'm going to open view dot blade PHP this one and scroll down below and right here we output post human read time so we save reload and here we see that perfect now I'm going to start working on home page and I'm going to define a couple of sections on the home page just modify that to make it more like a home page design where we're going to have an overview of our blog blog website like I'm going to display what is the latest post I'm going to show the most popular three articles actually let's open post controller or maybe we can start from web PHP and have a look so we have this post controller index method which is actually rendering the home so I think we should rename this method to home from here and here as well and at the moment we are just rendering 10 posts through the pagination so I'm going to completely remove this and I'm going to Define which is the latest post so we want to show latest post I'm going to show the most popular uh three posts based on upvotes I'm going to show recommended posts based on user user app folds if the user is authorized okay so if authorized however if the user is not authorized um let's not authorized let's define um popular posts based on views so and let's fix the typo and we are gonna also show top categories or maybe like a recent recent categories with their latest posts okay so I want to have these four main sections um on my on my website and let's open a home blade PHP and we are going to remove sidebar and everything and I'm going to define those um four four sections in the following way so we have this container and inside there I'm going to Define one div and that's going to be the header section inside that div I will have latest post section and I'm gonna have um popular posts popular three posts okay so that's going to be the second div and this will have let's give it proper CSS classes this will have a grid let's give it grid calls one but above medium screen let's give it greed calls three maybe let's give it also Gib four okay we should put this in a comment like this uh hold on okay like this we need comment here as well popular three posts okay and at the very bottom I'm gonna have two more div elements and this one will be recommended posts and this one will be latest articles um sorry latest categories like this okay perfect now we need to feel those gaps if I just type dummy text latest post here maybe we can Define also heading of that section like H2 let's give it proper CSS classes like I'm going to give it a text large and above small let's give it text a text EXO let's also give it a font bold and give it text blue 500 give it uppercase everything let's give it also padding button one and Border a bottom two I'm going to give it also border blue um Order Blue 500 okay and maybe small margin as well and inside there I'm going to type latest post now if I save this and have a look we have a nerve and the compact we don't pass anything so let's remove compact completely I say this reload the page and we see this latest post now that's good however this latest post I want to give it a call span 2. I want this to take the two third of the entire screen and then this one will have one third okay um I think this is good create grid calls one above why doesn't this take the to Third because this doesn't have full width and I guess this is the reason uh this one has Flex aha so we we need to remove this Flex it shouldn't be Flex okay so now this takes two thirds I think the container with for the home page is a little bit too large so I'm going to reduce it Max with maybe like a 3XL let's see how it goes um okay let's let's try let's start with this and have a look okay now we have this latest post I can copy this title and that will be popular posts uh here we will have recommended recommended posts and down below we have latest categories uh recent recent categories maybe or recent posts okay let's give it recent categories okay so we save this and we have uh four four sections as we as we defined now we need to pass proper variables to fill those sections right so now we need to work inside the post controller and let's start with the latest post which is slightly easier compared to others from post we are gonna uh query where active so first flag needs it needs to be active specify one as an integer we need to also Define uh where date published eight needs to be um less than carbon now okay so it needs to be published by date and Status means to be active as well so let's order by order by published it descending and I want to get limit one and then first okay I think I have everything correctly so this latest post now can be passed to view like this so now let's print if we have latest post here latest post save that and I do have this here and I'm going to actually use existing component X post item component and specify here post to be latest post okay save this and here is the latest post information on the home page awesome now let's move on the popular posts so how should we Define the popularity of the post we need to do this based on number of upfolds so let me create a variable first popular posts equals post uh let's run query let's join these we need to join this into upvote downloads table up vote down volts where posts ID equals to upvote down votes dot post underscore ID okay so we join this now we need to select we select uh we're doing it so we need posts everything from Posts let's also select number of upfolds for that post because then we need to order by number of upvotes and if we don't select put this in the select we won't be able to order by by that so in this case I'm going to use DB roll and specify here account upvote down votes ID and let's give it an alias is upfold count right so we need to add additional wear here we just don't want to query every everything from upvote downloads because there's a flag is upvote needs to be equal one we don't want those up for download records which has download right so in the weird I'm going to specify a function which will be query and on that query I'm going to run where upvote down volts is upvote equals one okay okay perfect let's add additional wear so we want those posts we basically need to grab this no this part because we want to get only those posts which has active one and published it is in the past and we want to order by this order by descending by the following the following name like a count of upvote down votes right so we specify upvote download here we also need to run Group by posts ID we don't want duplicate the records that's why we need to run Group by and finally we need to limit this to get three records and let's call get okay if I don't make any mistake we should have popular posts by their number of upfolds okay let's pass this popular posts right here let's go in the home blade and we have popular posts here and let's output that let's have a look okay we don't have any error it probably means that we have successfully implemented that so now we need to iterate over our popular posts for each popular posts is post let's create a div let's give this Steve greed greed calls uh maybe four let's give it skip two inside there I'm going to create one div which is going to be the image wrapper so in the source we're going to specify post get thumbnail let's specify alt to be post title like this and let's specify second div inside there we're going to have maybe inside H3 post title and we need like a short description like we have it in the post item so we need to use the same method short body short body here we have this method okay let's let's print it post uh short body I have feeling that this short body will be too large for that section let's have a look the second div should have called span of three so basically we are splitting the entire width on four equal spaces then this image will have one part in the description and title and the short body will have three part so if I save everything it should be like this okay an image and the title in the body this body needs to have smaller fonts so let's specify text SM okay that's good uh let's give it also text semi-bold okay I think that's good but again as I mentioned this description is too large so inside short body I'm gonna specify I'm gonna Define uh like Words variable which by default will be 30. so that's that's a good lesson to learn so I'm using this short body from somewhere else I want to modify this short body arguments so that it doesn't break other place if I just make this argument required like words here and then I specify words here it's going to break the other places because other places where I use this short body we don't pass these words variable so we need to make these words optional so that by default it still is 30 and from other places if we are using this short body we don't pass this 30 and we don't have any problems but in this case on home page I want to pass 10 instead of 30 10 words so now this is more liked okay that's perfect however on this container I'm going to give it like a slight padding top adding top Maybe two so this image is moved down and that's it you have it however why we don't see more than one post here okay don't we have other posts let's check the post controller so we joined this I put downwards okay I see the reason so because we write the left join here it basically means that upfo download might not even exist um on the post and in this case we in the we are close we have this now is upvote needs to be equal always one and that's basically what causes the problem so here we can specify we are we are null to be more specific so upvote download specify up vote down volts is up fold needs to be either null or its value needs to be one it will be now whenever the left join doesn't return any any anything basically so whenever the post doesn't have upload downwards this will be null however if there exists a record for the corresponding post inside app vote downloads table this will return record and then the value needs to be won so if I save this now and reload the page they break anything okay we don't see anything oops here we need or where the upflow down which needs to be now or it needs to be one so I think that it is here we go so now we have three articles right here because we basically are limiting to three so we have three articles image title let's make title a little bit like a maybe bold to stand out from from anything else um okay let's give it uppercase Maybe no I don't like text bold white Expo doesn't work as I expected is their text extra small on buddy okay if we reduce the body we can reduce this one as well so we give it a text small uppercase Maybe okay not paid and we can give this one also no wrap text no wrap or white space no wrap um okay I'm gonna look for this talwind CSS a white space no wrap okay I think this is the class so let's specify this here it goes on full width and let's search for also Talon CSS text overflow ellipsis okay I want to show simply three dots there truncate does that class do what we want let's see okay yeah this does what we want I'm gonna add extra margin margin bottom three between each posts like these maybe even four okay so the latest post and the latest popular post like a three post well I think that um the the text size is too small compared to the left one so we should probably even reduce the left side but in this case we are using the uh same uh host item component what we have on the other pages so changing this will affect the other Pages as well so I don't want to spend too much time on design part again like we can simply increase the number of items into five here um reload the page and again if we add extra extra things like well let me show you like we have this by who who is the owner of this article basically or what's the read time of this article or what are the categories so let's grab the categories section in the home page and let's put this below title here maybe so I save this here we see now JavaScript is a category we can slightly change instead of text blue 700 let's give it PG blue 700 and give it text white and padding padding two something like this padding one and rounded and instead of 700 let's give it 500. okay so we create this small small tags let's give it text excess extra small okay so those are the tags for that specific of that specific article and that section needs to have like a margin button as well okay we can this div is rendered now for every for every article even though there are no categories because we don't have this in the if statement we can actually wrap this if the post categories is not empty then render this part which I'm not going to do you can do it if you want I'm going to reduce this part adding tab on the image so the image needs to be moved a little bit up and I can finally give a slight increase on the container width okay so this is it we have the latest post we have the popular posts we can increase the Gap right here up to eight Maybe that's that's good that's good and of course whenever we click on one of the posts when it needs to open the inner page so if we go in the popular post section uh here maybe on the image if I change this into a and if I change this if I wrap this into a as well and give this one href roads um I'm going to check in the rotor here we have this View and I need to pass post so View and post and do the same thing here so I need you and post I save and reload the page and I see when I click on this it opens the article click on this it opens the article it also keeps track which articles I opened not too bad not too bad let's put extra button like we have on the post item continue reading button and by the way it's the the continue reading button doesn't have proper link here which we can specify like oops like we did here I'm going to take this href specify here now if I click this continue reading it opens the inner page and I'm going to get this continue reading and put this here okay the text size needs to be text s extra small and the arrow yeah here here it uses font awesome Arrow which is fine okay now we are more like uh filling all the missing vertical hate compared to the left latest Post article which is fine okay and we have these links also and clicking on the image everything is working fine okay so we have this now two sections of home page active and ready let's move on to the next one which is recommended posts I'm going to open post controller and let's now Define the I think this is very interesting part so first let's get the authorized user information I'm going to get this from auth user then I'm going to write an if statement if the user exists it means that we're going to write a different query if the user doesn't exist we are going to write different query the else part is slightly easier so I'm going to actually do this and it's very similar to popular posts so I'm going to get this however I'm going to modify a few things let's give it also name different name recommended posts so we start query from Posts we left join on poster views post ID equals to post views post ID then we select posts and post views ID is view count let's call this view count then we write additional wear uh this wheel basically is not necessary because if there is a record in the post views table it's just it just needs to be counted okay we don't care about anything else so I can remove this we are activities to be won and published it needs to be in the past that's totally necessary and then we have order by descending in this case order by view count then we have group by post ID and limit 5 and get so we have this recommended post we can already pass that that's for non-authorized users now let's define it for authorized users which is slightly more challenging in my opinion so first I'm going to define the main query and I'm going to Define sub query as well on which I want to make a join so the idea is the following I want to query posts which are in the same category on which in which I already upvoted some of the posts so if I uploaded for example a post from the JavaScript category in my recommended post I will see another post from the JavaScript category okay this is what I'm going to do so let's start defining recommended posts equals posts query we need a left join on left joint on category post let's give it to nalius as well like is in category both SIDS CP Maybe we are posts ID equals to CP post ID okay I'm gonna write another lift join but in this case I want a sub-qa and that sub query um let's let's call this um like left join there's going to be some sort of string I'm going to use that left join at the moment I'm going to also Define extraware clause here well I think we should first Define what should be this left join so that's going to be select from upvote down volts down volts we're going to join into category post as CPU on upfold downloads host ID equals CP let's move this down as CP host ID so we are selecting from upload downloads then join to category post and finally we're going to query we need extra wear closes here but finally we're going to query category ID from this category post category ID and we need a post ID and let's give extra weird we are upvote down votes is upvote obviously is upfold equals one and and the main thing is that we need to get this for the currently authorized user so and upvote downloads user ID equals to something so again let's have a look let's get this um get the full idea of this select so we're not query from our full downloads We are the current user has upvoted this where Clause means that and finally it's very simple and finally we're going to get the category ID and post ID okay so let's wrap this in parenthesis and let's give it a like an alias as T because we're going to write a join here on that and I'm going to give him give it an alias like a t so now we are left joining on the following query I'm going to specify here this join then on join I'm going to call T category ID equals to CP category ID so I am selecting posts which are in this same category the user upvote the current user app voted posts okay and I'm going to specify also we don't want to grab the exact same post user upvoted in the recommendations so that's why we're going to exclude t which basically at the moment is the upvoted pulse ID T pulse ID does not equal to CP post ID okay did you get the idea okay if not feel free to pause and uh listen to the section again so now we're gonna grab all the posts from here now let's put semicolon here and we select the post and now we need to set bindings so here we use question mark and we need to fill that question mark by the currently authorized user ID and finally let's call get on this and have a look if I didn't mean miss anything we should see some output of recommended posts on the home page so here we have that let's output recommended posts save this and have a look alt user with his auth manager user undefined property okay this is this is not a property it is a method reload the page okay we have some syntax error okay we do have that near post ID from Apple downloads okay let's double check everything select from upload downloads join category post on Apple downloads post ID equals category post post ID we are upvote downwards is up fault equals one and apple downloads user ID equals this one okay this looks correct so this is a left join section then front posts we left you into category post as CP on post ID equals to cppost ID and then here we'll let join on this it has nulliest TT inside join we add the category ID needs to be the same as the category post ID and the T post ID doesn't equal to category posts post ID and then we select posts here wasted bindings then we return okay where is an actual mistake I didn't get it okay we need to grab this and execute this in the database client to check if there is some mistake if there's a mistake we are gonna know about that I know it's no mistake here instead of left join yeah definitely we need to specify DB row so yeah of course like in this case as you notice the whole select is inside backtics it assumed that there was a like database expression column name or whatever but we need this in to be a row row SQL so I save this reload the page and now we still have something not correct so let's check now I'm going to grab this again and execute here and check what mistakes I have okay here's something here's something now where's the database here is the database here is the problem equals is missing isn't it yes join on category post on this where this equals to this so I save that reload the page and we don't see her anymore which is awesome and we see some recommended posts which is even more awesome okay we get how many records we get here we don't do obviously all records so let's limit this into five reload the page okay we see five records here we need to test if the actual result outcome of your query is accurate but we anyway need to render them and display them so let me actually first do this I'm going to use a grid layout again for this let's give it read and grid columns columns 1 and above medium screen let's give it Creed columns 3. then we use for each recommended posts as hosts and I'm going to use the same component X post item in this case let's specify host here actually let's select only three here and here as well so I save reload and just like this we see latest three posts well let's give it gap of three maybe just are broken which should not be but that's not a big deal okay I don't think the design really fits to anything else but I guess we can leave this now I we just can remove these parts it's not necessary so let me actually show how to remove this part so that we don't break other components where this part is actually necessary so I'm going to open post item component and inside the Constructor let's accept wine property public let's make it Boolean Boolean let's call this show author by default this is set to True show author public Boolean it should be blue right show author we we are using the following components so in the post item we always show this author we can write if statement if show author then we show it and by default it is true so we shouldn't see any difference somewhere we have a semicolon which is not necessary okay by default it's it works in the same way however in my home page when I use that I can specify show author to be false and let's see what will happen I don't see this author information here okay however I see this above again a great usage of component how you can use it so that you don't break how you can modify so that you don't break anything else okay now the question is why I see those components why I see this in recommended posts well the idea was my query uh the idea of my query was that two to show only those posts which I have upvoted and the other posts which are in the same category I have reported so I think I have upvoted this particular post so I shouldn't actually be seeing these posts so this we are close is inside left join and I guess this is not 100 accurate so we should add right here additional wear we are T post ID does not equal to CP post ID here we can use cppost ID or posts ID it's going to be the same so I save that reload the page and we have something broken let's see column T post ID invalid parameter number okay I think what we need to do instead of this T post ID needs to be wrapped in a DB row maybe because we have this t inside DB row like here this T Alias inside this DB row so if I specify it like this and we can let's change this into posts ID reload the page invalid parameter number is this actually a problem like if I comment this out yeah it works if I uncomment this it does not seem to be working okay let's check what is the actual select this is Select let's open and paste when to slow down and understand what's going on we are T post ID doesn't equal to question mark why it is a question mark well it should not be question right okay let's do it vice versa we are that's it post ID yeah we need to specify First Column name and then the column name operator and right here we just we need this TV row okay it should not be assumed that this is a value instead we pass DB roll if I save this and reload we see yeah this is exactly what I wanted to see so I see now two posts in my recommended posts and those posts are in the same category in the JavaScript category I have upvoted one JavaScript post and I see other two posts recommended for me because I have 40 JavaScript posts this is awesome isn't it so now if I go and let's give this one this total Managed IT okay whatever click edit let's give it JavaScript as well JavaScript category and when to make this active save enroll the page now we see this here as well in my recommended posts the image is broken not sure why [Music] um here it wasn't actually broke was it yeah whenever we update how whenever we update it the image gets broken and this is something probably we need to take care of if I click on this and edit I don't even see this image here even though the image is presented here okay we can take care of this this is a slightly different problem not exactly what we are trying to do at the moment we're trying to make the home page uh really active and working and now let's focus on recent categories okay before we move on the recent categories let me move this comment up maybe here for the else statement like this and now let's do this so in this case I want to select categories category query where um hold on so I want to select category with posts so I'm going to use weed I want them with a post let's specify any array here with posts I'm going to use function here we have query and then on the query I'm going to Execute order by descending I want to sort them by descending published it okay perfect we need to query basically only categories like select categories everything I want to also select select select row I'll select role um like the maximum date so what's the idea of the categories I should have probably started from there so what categories I want to show there I want to show the categories which contains the recently published article so basically it turns out to be a recent category because something happened inside that category a new post has been published like if there is a PHP category which has the latest post and recently I published a new Post in the JavaScript category the JavaScript category will need to like need to be at the top of these category lists okay so in the select row I want to select the maximum date of uh we need join obviously so let's try to join first left and join on category category post we are categories ID equals to category post um category ID okay we need to also join on posts where posts ID equals to category post ID and now we have from categories we joined to category post and join to posts and now I want to query what is the maximum published it date um let's give it an alias Max state which is the maximum publish date for that specific category okay and then I want to order by descending by this Max state so I order categories based on the maximum date of its published posts I hope this makes sense I can't explain this any better so Group by categories ID and then we're going to limit this to get the five categories and it should be integer by the way I don't know why I typo string and finally we call get now I should have top five categories with are sorted by the maximum published date descending of those posts inside those categories okay so I'm going to pass now these categories to to view let's do this on its own line like this and now if we go in the home blade this is the last section what we are gonna implement so we're going to iterate over categories is category let's create div we're gonna create H3 and let's output a category category title and then we're going to iterate posts and output those posts so for this um let's use Forge again category posts is post let's create I'm going to create one div again with class read and grid calls uh calls one and above medium let's give it grid calls three let's give it cap three as well so this combines all the nested holes and yeah for each post also we need only for each category we also need like three posts so here probably order by descending we can specify limit three as well now we have three posts for each category and and I can use the exact same component X post item passing post here and we can also pass um show author to be false we don't want the author to be displayed okay let's remove this extra div and see what's going to be the output below the page okay we see laravel we see PHP those are two categories but we actually don't see items here so if I print category posts let's see what it is yeah they are empty empty arrays laravel and PHP why I don't see why I don't see JavaScript inside categories okay strange so let's let's have a look so from category let's if I remove this with completely okay so I select categories I have this date left join everything okay this looks good reload the page I see no JavaScript here okay I see something promising so let's remove this and have a look so we see hold on recent categories here we here we go so this is Javascript and all the categories inside JavaScript okay then we have laravel and all the uh all the posts excuse me from the laravel and then we have PHP and all the posts from PHP okay if I specify I want categories with posts if I just remove this weird okay I still get that perfect now if I Execute order by um published it in the limit three that completely changes the picture so for JavaScript we see that but I think this limit three is added here so it actually if I specify limit to one now it works perfectly actually on on JavaScript well actually let's try to remove this wave and in this case we should see everything what we expect and in the home blade maybe I can execute get posts and provide the limit here and get the limits like a three let's specify only with three here okay if I reload category um that should be posts simply posts okay now let's check this uh recent categories we have JavaScript three items for lateral one and for p if you want so that actually works keep in mind that right now we are executing this query for each category well at the moment we have only five categories which is fine but if you have X amount of categories in categories and then you're going to execute query for each category uh you're gonna basically have a kind of database issues not maybe issues but you're gonna put extra load to the database so it's going to be good and I'm going to do this to debug why these parts this code doesn't work as expected I expected it to limit posts make a query for posts once and limit uh limit for each category but yeah I think we need to do it slightly differently so that's why I'm going to comment this out and again because this is a home page and we have a limited number of categories that's fine in my opinion in this case okay what we need to do is um either some formatting to this so this is like a text text large let's give it text maybe Center let's give this one also margin button like all of them plus margin button or maybe here as well margin button four I think it should be eight uh okay and we have this JavaScript here let's give it also font bold maybe even text the Excel okay not too bad give it margin bottom six okay that's perfect like we have recent categories and yeah of course that should work why it doesn't work okay probably because this article is not published and we cut something we don't specify here in the home blade we don't specify uh that we need published posts so if I open now post and we have this um from category basically we have these posts I can Define one more that's going to be published posts and we can run extra wear closes here and I'm going to copy this again from from here we are active in published status in the past like this click ok let's move this down and in the home blade I'm going to use published posts so if I say this now and reload the page I don't see anything in the lateral I see one PHP click on this that works however we don't have laravel category posts published and if we go in the post controller in the categories it's good to add one extra as filter his posts so basically if the category doesn't have posts it doesn't make sense to display it right here so if I just refresh the page I should not see lateral here but I see because it actually has one post and this has does not check uh whether the post is published or not so I think we can and add an extra Wear close here uh let's grab query okay I don't know if we can this has if that supports the filter okay laravel uh we're has something like this I think there's I remember now so there is something like where has exactly like this we specify posts and we specify function like this we get query here and then on that query we run where category active and this part and the publish that is in the past okay now let's check this refresh the page okay live will disappeared exactly as we expected there are no active posts in the laravel category that's why it should not be rendered if I open the page and search for I don't know which one is from laravel this one which is not active I activate this let's click edit then active save changes go on the home page refresh now we see laravel right here okay so this is our new home page we have latest post we have popular posts we have recommended posts for me and we have recent articles JavaScript laravel PHP any file logout recommended section should be different now I see different output right here okay I think this is this is really good all right I'm gonna make small design adjustments on the on the home page I'm going to remove these recent categories and instead put Javascript right here and I'm going to also link it to the actual categories page where you can find all the JavaScript posts and I'm going to also adjust the height of the image because right here we see that this one has smaller height this one has large so let's make it fix give it another like aspect ratio of like a three by four or something like this and then we we will be sure that we will have the same hate for article and then we will have title as well as the body like I'm I have zoomed in very very zoomed in version in my browser that's why I have a huge huge letters here and when you zoom out actually it's going to be tested in a hundred percent there there might be necessary to adjust the font size it says right Etc okay let's start with small things and then then we're gonna move on much much bigger thing which gonna be implementing comments comments section all right so let's open um this blog and I'm gonna go in the post item section here and yeah the post item component basically is used on multiple places right here and it is used right here and we also have it used on the home page um no on the inner page no this is something else okay anyway so we have this in two places right here and right here so we need to give it a proper aspect ratio to put the image properly so let's give this one um also out there's going to be post title but speaking about the aspect ratio let's search for aspect ratio Tailwind CSS there is one plugin necessary to be installed I'm not sure if this comes with the basic installation it might it might be coming okay let's check um we don't own Square here we have that aspect Square we can customize that and provide three by four or four by three as we want or provide it like this like arbitrary value this is what I want in classes for the Post item so let's give it aspect three by four no four by three we want it to be in the landscape mode well that's why let's specify 4x3 if we reload page we see huge image okay the good thing is that the hate now is always the same and I think that's much better but the images images very stretched which we want to fix so if we specify objects cover let's have a look okay now we don't see the whole image let's specify object contain okay I think this is what we want so we have image always visible we have three four by three which which is kind of okay however we can even customize this post item component just like we customized let me show you so right here we have this show author and in the same way we can add one extra parameter which will Define the image properties image aspect ratio whatever we want and then we can use these for um for like big size we can do differently for uh for below we can do it different like this is fine for me but this is a little bit too large isn't it okay we can leave this at the moment I'm going to leave it one additional thing the images are broken and that basically happens because we are using seed data and we don't have actually uploaded images if I just click on this and if I make some changes right here then these images is not going to be lost like specified 2 here save that below the page we see two right here but the image is not lost images are only lost whenever we update that specific article which has that seed dummy URL right there save changes go back and then this is actually lost but that's fine because we are not gonna spend time on to fix some C data which is only created for like demonstration purposes okay I think we can move on the comment section uh before that actually um as I said I want to change these recent categories how that is rendered so I'm going to look for resend categories here I have this on home page and I'm going to move this for each right right here okay then this end for each goes out right here so now I iterate over categories instead of recent categories I'm going to type the category title right here that's perfect and we also have these uh continue reading icon Arrow icon I'm going to copy this icon and put this next to the category title so if I say this now I see JavaScript with the arrow and I'm going to make this Arrow to link on an actual category page if we open web.php we see we have this the following URL by category we need to provide the category slug so let's use root by category and actual category so I save this reload the page and if I click this right now it opens the category laravel and shows me all the posts I have on laravel category which is exactly what I wanted okay I think this is awesome so we have recommended posts and then JavaScript okay I'm gonna add additional text right here hosts for category JavaScript like this here we go pose for category JavaScript post for category laravel and so on I think category reliable this will be also good enough all right that's it for this video and I hope you like it if so maybe you want to hit the like button and maybe you want to check my another project where I created portfolio the codetholic.com in laravel 9. you can find this video right here thanks for watching and I will see you in the next time
Info
Channel: The Codeholic
Views: 23,541
Rating: undefined out of 5
Keywords: TheCodeholic, laravel tutorial, laravel project, laravel 10, laravel 10 project, laravel 10 tutorial, laravel blog, laravel build website, laravel 10 blog, laravel 10 website, laravel project tutorial, laravel blog website, laravel docker, laravel 10 admin panel, laravel admin panel, laravel website with admin panel, laravel blog with admin panel, laravel filament, laravel filament PHP, laravel blog part 2, laravel 10 blog part 2, laravel projects, laravel blog project
Id: 2ZkePm2D6SI
Channel Id: undefined
Length: 176min 39sec (10599 seconds)
Published: Thu Apr 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.