Build A Login System in PHP With MVC & PDO | Includes Forgotten Password

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we will be making a user authentication system in php from scratch using vanilla php with pdo and object orientated programming so here is what we'll have at the end of the video don't make a fuss over the styling of this project i know that it isn't great but since this is a php tutorial the styling is less of a priority and to save time you will start the tutorial with the style sheets already made but as you can see very simple application there isn't actually anything that you can do on this application other than the authentication procedures which are the focus of this tutorial and as is expected of any authentication system we are not currently signed in and we don't have an account so we can click on the sign up to register a new account now all of our forms are validated on the back end so you won't be able to proceed without passing basic security checks like ensure that we have completed all of the inputs and made sure that the passwords match etc now unlike other php tutorials that teach these types of form validation error messages the version that we will be making in this tutorial are not persistent meaning that they will disappear if we refresh the page and for the sake of simplicity i will set the password to simply be password an extra security check will prevent us from submitting a registration form if either our username or email matches that of an already registered user and our application knows this by querying the already registered users database and as you can see we've already got the email in the database which is why we got the error so great we should now be registered and we can check our database to see whether a new entry has been added or not and as you can see it has so we should now be able to log into our account and we can use our password along with either our username or email to log into our account and it does not matter which we decide to use they both work just fine so we'll now fill out this information making sure that it matches the data that we submitted when we registered our account but take note of this forgotten password link we will get to that in just a moment and now that we are logged in we get redirected back to the home page where we are greeted with this message that now displays the form name that we submitted on the registration form instead of guest which is what it said where we were an authenticated user and just like how we signed in we can now sign out as promised the greeting message will change appropriately and so does the navbar in fact we will now demonstrate the forgotten password feature that will also be taught in this tutorial so say if we are trying to log in but can't because we have forgotten our password for example well we could click on this option and be taken to this form where we can submit the email that we want the forgotten password instructions to be sent to now that we have submitted our email we could check our emails inbox for password reset email note that we are using mailchap as our email server of choice for this tutorial because it is very quick and easy to set up for testing purposes so imagine that this is the inbox of the user who just typed in the email a moment ago well we could see this new password reset email clicking on it we could see that it contains a link that we can visit if we follow the link then we should be taken to a page on our application where the user can reset the password note that for security reasons this password reset link will cease to function after a certain period of time but since we have met that time frame we will now reset our password and now if we try to log in for old password which has password then it will not work we will only be able to log in if we type in the most recent password after the change now it is worth mentioning that i created this tutorial because i was disappointed by the quality of php authentication tutorials already out there on the internet in both video and article format it seemed that you couldn't find a comprehensive tutorial that didn't have one major flaw if they did write php code in an ordinary fashion using a streamlined nvc object orientated pattern or pdo a must for writing vanilla php applications that's unmaintainable then they left out imported functionality like a forgotten password feature or they glossed over important details and the explanations were poor if they were comprehensive and the explanations were serviceable then chances are they wrote spaghetti code because they decided to write vanilla php code which is notoriously unstructured in procedural programming which led to a lot of copied and pasted code and projects that were all over the place and were just unmaintainable this tutorial sets to put those problems to rest and produce a php authentication tutorial that is a quality reference for people who want to get their grips of php now we won't be producing a framework here we will be producing the mvc pattern but the preliminary work will be kept to a minimum therefore this project isn't as structured as it could possibly be but i think it would be fair to say that this is a huge improvement from a lot of the php authentication projects currently being taught out there on the internet oh and by the way the completed projects github page will be posted in the description box below the database won't work but it is a good reference in case you get stuck at any point during this tutorial so without further delay let's now begin the tutorial so here we are in the project that we will be working on throughout the length of this tutorial as i mentioned before we've already set up the styling and the markup because covering that would detract from the tutorials focus and because this tutorial already assumes basic frontend skills and before we begin it is worth mentioning that i'm using xampp to set up my php project because it gives us an apache server and mysql database both for which will be used in this tutorial and because of this our project is found within the htdocs folder of the exam installation directory because this is where all of our projects are hosted on the apache local server which as you just saw we have already started along with the mysql server also since we are working with pdo it is necessary that we ensure that this line is present in the php the ini file in the php installation directory and it's important that it doesn't have a semicolon at the start because we want to enable it so that we can use pdo and on phpmyadmin which you should be able to access due to exam and we will create a new database the database that our new project will use so we'll call it login system yt yt because this is the youtube version of the project which i've already tested out and you saw that to start and this is the application that we have thus far being hosted on our local server via apache and don't worry there's no authentication so we just click this again nothing's going to happen not even if you fill out the information because all of that authentication will be done with this tutorial all we've done thus far is just do the views which you should already know because this tutorial just assumes basic content skills the first step that we will take to give our php project an authentication system is we will create a database class it will connect to our projects database and will be used by all of the models to query the database with pdo and fetch the results etc we will create it in libraries because it is not necessarily a part of the nbc architecture but it is necessary for us to streamline the model's communication with the database at least it is in vanilla php anyway and this file will only contain php code so we will open up a tag at the top and won't have a closing tag below simply because we don't need one and it will be a class that we can use its methods and properties etc [Music] these properties are all necessary data to connect pda with the database that we have just created for the project hence why its name isn't stored in db name as for the host that is where the database is currently stored in localhost and in mysql the default username is root and there is no password by default meaning that if you haven't set one yourself then you can set this property to simply be a blank string but in my case i've created my own password which is why i've not used that as for these fields they all relate to pdo dbh will eventually be assigned the pda object but if the assignment process is unsuccessful then error will report the error triggered and stmt will hold the query that we want to make with pdo we will initialize the pdo object in the construct method because that is what is called as soon as the class is initialized then we will initialize the dsn or data source name be very careful here if you make a syntax error then pda will not work and what we are doing here is essentially concatenating the relevant properties of this class using dots in the places where they should be in this dsn then you will configure some pda properties you won't go overboard here attr persistent means that we will always check for an existing pdo collection before creating a new one and attr air mode is simply a more elegant way of handling errors in pdo as for actually initializing the pdo object we do that in a try catch block so that we can catch any errors that may arise during this process now in case you don't know how pdo works any data from the client that we want to use our sql queries won't be directly added to the sql query because doing that would be a huge security liability and will leave us vulnerable to things like classic sql injection attacks instead our query which will be prepared by pdo will have placeholders in the areas where we want to use data submitted from the user in our sql query and since the statement has been prepared with pdo we will be able to bind the actual data from the user to these placeholders and that is a much more secure way of doing things because binding the data format stumps that they won't harm our sql query and this is the method that we will use to prepare query wikipedia and it does that because it uses this dbh property and if this try catch block go successfully then this dbh property will actually be pdo now as for binding the values to this now prepared statement pdo gives us two ways of doing that name parameters and positional parameters for the sake of simplicity the method that we will be creating to do this will use name parameters where the placeholders are listed and targeted by their name not their order so type will be null by default unless it is manually assigned a value on method call and if it is no then you'll need to figure out the data type or the value that the user wants to bind to the prepared statement because unlike php pdo is strongly typed and we will use a switch statement for that if none of the above conditions are met then we will automatically assume that the data being inserted as a string which it is most likely to be anyway and once that is out of the way we will actually bind the given value to the prepared statement once the prepared statement has finished being prepared we will be able to run the query with this method but if we are querying for a set of data then it is likely that we want the results returned so that we can work with the query data in php to do that we will create these two methods they will be called instead of the execute method because they call the execute method themselves and they both return the data as a php object the difference between the two is that the first one will return an array of objects meaning that it should be used for fetching multiple rows and the second method will return a single object the first row found that matched the query and this is why it uses the fetch method instead of the vector method like its contemporary finally this method will tell us how many rows match the query that we just executed with pdo and this will be the last method in our database class it is now time that we got onto creating the users table which will handle all of the users who have registered for service so we'll click on sql in our database and we will write out the command to create a new users table here the table will have a user's id column and that will serve as the primary key which automatically goes up by one and can never be null as for the other columns they also cannot be no and they are variable characters or strings that could hold no more than 128 characters and we'll now run this and we should successfully create the table as you can see all the columns are created here and actually we'll go to our signup view the one that displays the signup forms the user and you should be able to see that all these inputs match the names as the associated column of the users table that we just created and all of these inputs are present apart from the user id there's no input for the user id because that's the primary key and it gets automatically generated and it's just worn up from the previous row in the users table and currently this form sends a post request but it's not sending it to anywhere as specified by this action attribute so we will set it to send a post request to this user's controller which we need to create and to distinguish this post request from other post requests which might also be sent to the same file we will add this hidden input to the form hidden in the sense that it won't be visible to the user its name will be type and its value will be register because that is why we are sending this post request to register the user and as promised we will create this file in the controllers folder as referenced by our forms action its name is plural because it is a controller and it is the models that need to be written in the singular the controllers class had the same name as its file inside we'll create this method and it will do just that it will register the user and we want to call this method in response to a post request from the registration form and to do that we will go below the class and we will initialize a new object from the class then we will use the server super global and its request method field to check to see if the client has accessed this file via a post request if they have then we will check the value of the hidden input and we get access to it through the type field of the post super global because remember that hidden input had a name of type and on the register form that we just created we gave it a value of register therefore if we are receiving a post request from this register form we will now call the register method of this user's controller class now this user's controller is responsible for handling data that the user submits through forms but his ultimate goal is to use this data in communication with the database and the controller can't do this on its own because that is the role of the model and so we will create that now inside we will require the database file that we just created because this model will make use of the database class which is contained inside of that file to make queries etc we will initialize a new database instance on the db property as soon as this user model is instantiated and with this model created we will require it and the corresponding controller that we can use it inside of this matching controller then we will initialize a new instance on the model as soon as this user's controller gets initialized which happens directly below the class the first thing that we are doing this register method is you will sanitize all of the data being sent by post on the client the options that we use inside of this filter input function will remove anything that is deemed unsuitable for the format of a php string next you will create this data array it will hold the values of all of the inputs that the user sends over via a poster quest other than the hidden input and they are all trimmed to remove any white space that they might have had with the data formatted we will check to see if any of the items in this array are empty if they are then we will need to for an error of some kind because we can't have the user submitting a form that they haven't even completed and the error that we fire will be manifested in the form of that red box that's appeared above the form when an error was triggered and you saw this at the start of the video and we will create this effect with a separate file to save us from rewriting the same code as nauseam so if we don't specify otherwise then the message box rendered by this function will be a red error message as determined by this default styling that we created before the video even began if the name and the message argument are not empty and we cannot find the corresponding data in the session which is data that is globally available so long as the session has been started and hasn't ended then we will store the message in the session under a field of a name matching the name argument and we'll also store the class in the session in a field with a name that is a slight modification of the name argument if there is no message argument though and there is still a name arguments thanks to this parent if condition which is else if is inside of then we will use a ternary operator to retrieve the class from the session if it does exist if it doesn't then we will simply use a class argument which is assigned a value by default in this argument here and we will use it on the div element which will then be rendered out with this message which feed from the session finally we will unset both of these values in the session that's on page refresh the message will be gone because it gets unset as soon as it is shown and so the previous if condition here will also be met where the specified name on the session is blank and that is to happen before they could even assign and message on the session extremely start to semicolon this will just edit and for this to work it's absolutely vital that there is a session running so we will start a session on this file just in case there isn't one already running finally we will create this extra function it will simply redirect the user back to location specified by its single argument and then stop whatever script is currently running using php's built-in header and exit functions and back in the users controller we will need to acquire this to make sure that it works properly so if the error scenario is met then we will use the flash function to assign an error message to the session field of register and then we will redirect the user back to the signup page and to actually display this fast message we'll need to go to the sign up view we'll need to require the same session helper file and then we'll write the flash function with just this name argument and it needs to match with the messages set uh for the relevant function obviously in the user's controller so its name is register and then we'll display all of the register messages here and now we'll just test this out so we will go to application we will say sign up you know they're just the same thing click sign up and then obviously we get that message now but if we refresh then it's gone the next error scenario will be if the user has tried to submit a username that contains any characters other than numbers and alphabetical characters in either lower or upper case we test this with the peg match function straight from php it uses regular expressions which we don't have time to go into right now but our error scenario will be triggered if the condition is not met which is why we have this exclamation mark prefix we are saying if the username is not comprised of these characters then for an error as for the email we will find error if the user has not inputted anything that resembles the basic structure of an email and we can detect this with the filter of our email setting which is being used on this php filter of our function again all of these functions come straight from php so you can look at the documentation for a more in-depth explanation on what these functions really do the two password inputs will have two error scenarios the first one will be met if the user has inputted a password that is less than six characters so it is deemed too short the second one will be met if the user's password does not match the repeated password and the final error handler which you haven't created yet will be if the user has input of the same email or username as a user that has already been registered with us and to find this out we will need to go to the user model to make a query to the users table so you will create this method and it will take in two pieces of data necessary to make the query and we will use the database class and the query method that we created for it a while back to make the query where the queried work can match row can match either the email on its email column or the username on its username column and these values after the colon are placeholders we are going to bind data to them so that this becomes a legitimate query that we can make with pedia and this is us doing that we target the name parameter with the first argument and then the second argument is the value that we want to take in its place then we will execute the query like so using a single method because there shouldn't be more than one user who matches this criterion if any because that would defeat the whole point of making this error check so the aren't zero rows returned and while there's more than zero then we will return the matching row else we will return false making the non-error scenario a value of false for this method and back in the users uh controller we will now use that method that we just created on the user model and that is why it will for an error if there is a value from this method because if there wasn't then we would catch a statement with an exclamation mark prefix which would correspond to a false or null zero etcetera and obviously you know these exclamation marks here is what i'm referring to so if you get to this point then we have passed all validation checks in which case we could safely hash the password because we will soon be storing it in our database and don't want sensitive data like a password stored in our database unprotected and this is us doing that we use the password hash function which is a very secure method which comes from php we will now need another method on our user model where we register the user by inserting their validated inputs into a new row on the user table we only need a single argument because all of that data was stored in an array member and this is the crew that we will make there are four query parameters because we are inserting four pieces of data into a five column table four values means four values to bind to this pda prepared statement and we don't need to get back anything from this insertion command so either returned true or false depending on whether the insertion was successful or not i'm back in the users controller if all is going to plan with the register method then we will redirect the now registered users login page where they can then log in with the account that they just registered but if for some reason we failed then you will simply stop the script with an error message because there isn't a great deal that we can do about that and so now we should be able to test this out and see that everything's working as intended so you go to register and then we say you know john doe and then type in an email but what happens if we just don't type in a proper email but then obviously we fill out everything else and there is you know kind of an error with this because when we get i know it's like invalid email which that was obviously then we need to retype everything and there are ways to fix this in fact i've actually got a video quite a while back on my channel on how to use local storage to solve this error but we won't go into it now because this tutorial is already uh very comprehensive you know can't really cover everything otherwise it would be 10 hours long but anyway this should be valid now our password is just password we typed out twice the same and then yeah well we're in the login page so we should have passed all the validation checks we refresh our users table and as you can see even though our password is password it doesn't appear that way in our table because it's been hashed it just appears you know just a hash and then um what we'll now do is we'll now do the login so we will go to our login view and we'll need to send the user to the users controller when they submit the form obviously and to distinguish this post request from the register post request we're going to need to include the hidden input again and its value will be login into the register and just to save us from having to do it later on we will now include the flash message for this form even though we haven't actually created any for the form yet we'll just do it so we don't have to do it later on and the name for these form flash messages will be login and now in our users controller we'll need to handle this post request from the form from the login form sorry and yeah when we do get a post request on the login form we'll call this login method on our users controller and obviously you need to create this so we will begin this login method with the same formula as the previous register method by formatting the data as that is ready to be inserted into any prepared statement and just like before your phone error if the user has left either or both of the inputs blank and if you're wondering where this name slash email comes from that's actually the name of that email because a member they could either type in their username or the email as for this user's pwd well that input name is already used on the register form just in case you are you know wondering where this came from we will now make use of a method that we've already created from the user model to query the database for a registered user that corresponds to the data that the user just inputted on this login form so if there is no user then we refer an error because obviously they're trying to log into a user which doesn't even which hasn't been registered but if we know that there is a user who matches the inputted credentials then we will need to begin the locking procedure and to do that we'll use this login method from the user model which we now need to create which is why we get an error we could actually make use of a previous user model method in this one to find the user who matches either the username or email of the data that was submitted by the client and if there isn't one or the query failed then we will return it false before continuing with the methods that's an error scenario can be triggered in this login method but if we get to this point then we should have found a registered user in which case we will extract the password which should have been hashed before it was stored in the database and we will use php's password verify function to check the unhashed password argument with the hash password to see whether they match or not if we do then we will return the queried row and if they don't then we will return false because again we will have another error scenario and so back in the users controller if the login does end up being successful and not returning false then you'll pass the queried row into this method it will store the user's id name and email in the session that this information can be globally accessible files application as long as there is a session up and running you'll also redirect the user back to the home page and import the thing to note because you want the home page to now show the user's full name as they are logged in and as promised we will call that method if we are successful and this will effectively log the user in as for getting the home page to display the users for name we will say if there is a user id on the session then we will split the username up which should be on the session if that condition is met and we will split it up by its white space so we can access the first item from the array that has now been outputted by php's explode function to render out the user's full name with echo and if there is no user id on the session then we will render out guest because that should only happen if the user is not logged in and now actually go to the the header and we'll need to change the miss as well so if the user is logged in or sorry they aren't logged in because this is false then we will say they will you know have the option of either signing in or logging in but if that if this is else and we are logged in because this is actually set then we will show this login so i just log out and clicking on it it will send the user to the user's controller but we may want to personalize this get request a bit more so we can send multiple get requests to the same controller that's all do different things to do this we can add this query parameter to the url its name is q and its value is log out we will cover more on how to handle this query parameter from the controller side later on but for now we will try logging into our account and so we will you know just try this out so we'll type in you know the wrong information no user found obviously we'll type in you know no information and then we'll refresh to go to that and then we'll type in the correct information password is password that's our email login welcome guest okay i don't know why that's okay the reason why this isn't working is because we haven't started because on this header what we need to do is we need to start the session so that we do that on the um on the helper file as well but we do it on the header because this is required before the helper and that only starts if it wasn't started already on the header so now um well we should yeah we should already be logged in because we just we already started it we already logged in now we just started the session so now this is working as you can see the navbar has changed as well and what we now need to do is to do the logout functionality but before we do that we will handle the user's request so if this file is being requested from something other than a post request then we will create this switch statement where we examine the key parameter which is the query parameter that we set to be log out on the href of the eponymous navbar link and so if it does equal log out then we will call this logout method from the user's controller which we need to create lcd will redirect the user back to the home page because they are trying to access this file in a way which we are not prepared to handle and we'll also do that for post as well because when we're not uh we don't have a way of handling any of the other post requests that they might have sent as for the log out method it'll be very simple all it will do is delete the session fields that we set in the create user session method then ensure that this session is complete is completely destroyed and finally will be redirected back to the home page and so now we'll just demonstrate this real quick you know log out boom we're logged out easy as that now now that we've done the full log the authentication system what we now need to do is the forgotten password feature and if we go to our login form you may have already noticed that we've created this forgotten password option and it takes the user to this reset password view and on that reset password view they've got a form where they can type in that email and then they press the button to receive the email so what we now need to do is we'll now need to actually go to our database and we'll need to yeah so we'll run it from here we will create a new table and this will handle the forgotten password uh everything to do with the forgot to password what's it yeah so i'll create that table now and so this is what the table will look like so we have five columns and you know we've only been putting data into for them now because this one is the primary key which is also incremented again it's already been explained and then we'll run this and hopefully yep it's been created as you could see here the columns now to actually send an email from php will require a mail server for this tutorial we'll be using mailchat which is a mail server that is specifically designed for development apps not production apps that is because the emails don't actually get sent to the recipient when we use mailtrap instead they get sent to our mailchimp account where the intended recipient will be listed alongside each email this allows us to test multiple emails and and ensure that they are all being sent as intended we will now create an account with them so that we can you know use their service great obviously i wasn't going to show you my account details and we'll go to php mailer which is what i'll be using and to install php made i wanted to go to this github page again link will be posted in the description the reason why i'm installing it i mean you could use the standard php mail function but that is quite low level and this is much less painful to work with so we will go to download zip and then we will we will go to our you know our project folder in the htdocs and then we'll just download it there and then inside we will extract it yeah we'll extract it like this extract to php mailmaster obviously you might be using a different file archiver so once we we'll just rename this just for ease phpmail i like that and then all the files are in there and that's fine and we deleted the original archive as well and once we've got it in our project what we'll need to do we'll need to create the reset password controller and the matching model so we'll create them like so remember keeping following the uh plural for controllers single for models and inside of the reset passwords controller this controller will make use of both the user and reset password models along with the session helper file these functions were used profusely in the user's controller along with that you'll import these three files required from for the php major dependency to work along with this use statement above the actual controller class itself have three properties two for the models that we just imported and one for the php mailer dependency as is standard we will initialize the model in the constructors that they are initialized as soon as this controller is initialized and we're currently getting an error because although we have actually imported the reset password model we haven't uh created the class so we'll just do that now okay we're no longer getting an error now as for uh initializing the php mailer class again we'll need to go to our mail trap and we'll just copy this and then also about your code editor of choice source code editor but in vs code you can highlight and then press ctrl d to highlight the next matching uh text along and then we'll just target the mail property and then yeah this should all be good now we'll now go to our reset password view and just like before we will set the action it will go to the reset password controller and we'll have this hidden input that will enable the controller to respond in different ways to different post requests and as with before we will create this logic that will handle the different requests being sent to this controller the value of the hidden input on the reset password form submission that we just set is send and we will handle that with this sent email method which we need to create we're only taking one piece of form data here so it is a lot easier to pass and sanitize incoming data and as always we'll perform the usual check we won't explain what it does here because i've already covered what this logic does early on our database will store two tokens the selector which will be used for querying the matching row on the database and the token or shall be hashed when stored and validated with the unhashed version to check to see whether the user has the right to set a new password or not creating two tokens instead of one multiplies the security by two as for how they are created they are created randomly with this random bytes function which generates a random number of bytes as determined by the number given to the method as for the bin to hex function that converts the bytes into hexadecimal note that hexadecimal isn't hashing so this won't increase the security of our tokens we do it because we want an easy way to store these tokens and byte is an incredibly impractical format to work with and we don't convert the token into hexadecimal because we want that stored in our database hash not in hexadecimal we will then create this url it'll be the url that the user will receive in their inbox and can click on to reset their password the url here points to localhost but that will need to be changed obviously if we're hosting our application somewhere else as for the specific view that they'll be pointed towards that will be the create new password view which like all previous views in this application has already been created and notice that we have two query parameters here selector and validator we have used string concatenation to assign them the values of the matching tokens we do convert the token variable into hexadecimal here because otherwise the url wouldn't be formatted correctly for security reasons we want to invalidate this url after half an hour of its creation date to do that we will store the current date plus 1 800 which is half of an hour in seconds to store in seconds since january since the first of january 1970 the time exactly half an hour forward from now and now we'll need to go to the reset password model like with the previous user model we will require the database class that we can make basic communications of our database and we will initialize it in the constructor so as soon as this model is initialized with this out of the way we will create this function it will take in an email and we'll delete the vote from our password reset table that matches the given email if one exists of course again i won't explain so much detail now because we have gone over these principles many times by this point and back in the controller we will use uh this method because if there was an existing password reset entry on this table that had the same email as the one that the client had just sent to us then we will need to delete it because we are about to submit a new one and that could only be one per email if for some reason this delete query fails then we will throw an error past that we will hash the token like we said he would and get ready for his storage in the database and in the model to insert a new entry into this table we will create this method in the password reset model the query made will have four parameters because that is how many columns we'll be inserting data into when we create a new row in this password reset table and with this created we will make the insertion with the data that we have prepared at this point and if this insertion was successful then you'll begin sending the email below this the messages subject is self-explanatory as for the messages content we use html for that because we want the message that spans multiple lines and we can use paragraph elements to achieve this effect as for this dot equals syntax what we are doing here is appending new content to the all the existing content in the message variable the dot ensures us that we are not overriding the existing content the final thing appended to the message will be this link tag its content will be the url and clicking on it will take the user to the very same url that is why we have used the string concatenation that we have used again very important that our syntax is correct here there are a lot of room for errors as for who the email will be from it doesn't really matter we could choose any old email and here we've just decided to use his boss email next we will configure the messages subject and body but not before setting the email to work with html since that's what we've used then we will add the emails recipient and that is important it needs to be the email that the user sent to us finally we will send this email and once sent the user will be redirected back to the reset password page where they should see a flash message but this time the message we green as configured by this third class argument which is normally omitted because it is assigned the error class unless a specified value is given and in the reset password view we'll use the flash message like we always do so you can so the user could actually see the success message and so now we can test this out hopefully it works so we go click log in oh no you forgot that password we've only created one account so we'll just type that in right now and that was the email for this only account that we created yeah we had to wait a bit for the magic to work and then we go to mailchat hopefully yeah we should be able to see it now and then we click on here and as you can see it takes us this view that we've already created and it's got all these the correct query parameters as well so this is good and as for this uh create new password view here it is here we want to shake things up a bit we only want users to be able to see the form if they are visiting this file from a link which contains the two token query parameters on the url and this will prevent people from accessing this page when they shouldn't be and so now we will only render out the form with all the other content header and all if not only does the uol contain the two query parameters as determined by this if condition here but also if the two query parameters are in hexadecimal format as determined by this c type x digit function we will turn a simple error a message if either or both of these conditions are are not met so one here if they are empty and one here if they're not in hexadecimal format again it is very important that we get the syntax right here the actual form and these two include should be contained within this child if condition and we should have this closing php tag at the bottom where the semicolon of the parent if condition is closed off and an else condition for the child if condition is made what we will now do is along with creating the type hidden input and setting the forms action which is what we always do we also create two more hidden inputs and the name was corresponds to two tokens which should be present as query parameters on the url if you have gotten at this point the values of these two token inputs will simply be the matching token and that's straight from the ul query parameters and we assign the variables here and so now in the controller we will need to handle uh the post request from this reset password form and here it is here again we can take it now because i've actually created that yet so you will create it just so you don't get an error and i'll just show you real quick that say create reset password but we're going to move on this now so could not validate you well that's the error but obviously we go back to this link here then is working now because that will actually have proper validation to access it in that case and in this method we will sanitize and pass the data as we always do then we will actually reconstruct the url that the user should have visited in order to send the post request and call the specific method in the first place we admit the local host part here because this url is for redirection purposes only and so we don't need it and as is a standard we will catch any errors with the input of data and if any are met then we will do what we always do and send the user back to the form with an error message after we will extract the current date in seconds to see whether the url has passed its expiration date or not and in the password reset model we will first need to find the vote in the password reset table where the selector token matches the one that the user had on the url and where the expiration date stored on the road is still great in the current one we will need to create a method that will determine whether the user can actually reset the password or not and so you'll first need to find a vote in the password reset table where the selector token matches the one that the user had on the url and where the expiration date stored on the row is still greater than the current date if said row does exist of course and so now we'll implement this in the controller so if there wasn't a row that matched this query as determined by the row count method then we will need to inform the user of this error if there is low then we will use the queried row which we stored in the above if statement to check its stored hash token with the same corresponding unhash token with this already mentioned ph password verify php function and if they don't match as specified with the exclamation mark then we will need to catch this error else we will continue with the password reset process we will now use the email on the password reset road that we have just queried to see if there is a user from the users table who shares the same email if there isn't then we will throw an error because there is no password to reset and what we now need to do i actually need to go to the user model because the actual query to reset the password will be handed on the user model since all of the user's passwords come from the user table to begin with we are finding the user by their email and are using sql's set command to change the password to the new password which is bound to the pwd parameter and so now that this is created we can use it in the password reset controller if we have gotten to this point in the reset password control is reset password method then we should now hash the user's new password because the original one was also hashed and then pass it into the user model method that we just created which updates the password to the supplied new one we will finish off the labourers method by deleting the row from the password reset table that we have just used because the user has now successfully changed the password and then and then after this providing that there was no error with that delete or email method then we will redirect the user back to the password reset form with a success message indicating the result and finally on this create new password view we will do flash message okay and before this we test this out there is actually i didn't notice an error it's basically the link that i used here was in relation to my test project but not the one i'm actually working on as you could see here it's got a hyphen wide hit the end and so what we're doing is before i was sending a link to my other um project which is already which is already i use a completely different database and that's also hosted on local server because everything in the web in the web folder is hosted and basically it was just messing things up so now if we yes we need to go back to the beginning basically we click reset forgotten password i've only got one uh email well one registered user that's the email that it uses and so now i've sent as you can see i've sent quite a lot now but if we go back we should only see one because remember we've only allowed one per email one entry per email we click on this it should be the correct link now type in the new password would say one two three four five six seven eight nine same with this one two three four five six seven eight nine and now okay we receive email i don't know why that uh oh wait probably because what did we do we said new reset and then create a new password okay we didn't we didn't do that does it really matter yeah so we refer password updated okay now we log in and then we say you know that email and then we say our old password it shouldn't work now password incorrect but then if you go one two three four five six seven eight nine and then yeah welcome john john doe and that's it for this one guys i hope you learned a lot from this tutorial especially if you are new to php and are finding it hard with the lack of quality php tutorials out there on the internet please give me your feedback on whether you want more php tutorials like this one or not and don't hesitate to contact me if you're stuck on anything covered in this tutorial and can't figure it out from the completed github project in the description box below more importantly though peace out guys and have a great day
Info
Channel: Qixotl LFC
Views: 1,679
Rating: 5 out of 5
Keywords: qixotl_lfc, How to make a login system in PHP with PDO and MVC pattern, How to make a login system in PHP with object orientated programming and MVC, PHP login system PDO tutorial, PHP login system MVC tutorial, How to make a login system with forgotten password in PHP, PHP login system with forgotten password tutorial, PHP login register signup logout MVC PDO object orientated programming and forgotten password, PHP build a login system with forgotten password, PHP forgotten password
Id: lSVGLzGBEe0
Channel Id: undefined
Length: 52min 40sec (3160 seconds)
Published: Sat Jun 26 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.