Creating an App from Scratch: Part 5
All Series Navigation
Where Are We?
Now that we have a workflow put together and the HTML and CSS to make it look good, we can actually start building the classes that will run this puppy.
We’ll focus this installment of the series on the user’s account interactions. These include:
Connecting to the Database
Before our class will be able to do much of anything, we need to connect to our database. To do this, we’ll need to create a couple of small files.
Defining Site-Wide Constants
Our site won’t require many constants. but in the interest of keeping them easy to maintain, we’ll create a separate file to contain any information that is site-wide. This will be called constants.inc.php. and it will reside in a new folder called inc — this folder will contain our PHP classes as well.
Creating a constants file is a good idea for pieces of information that will be used often and in different scopes throughout a site. That way, if your database changes, you’re able to change every database connection simply by swapping out the information in one file.
Inside constants.inc.php. we want to define our database credentials. Since we’re starting out by developing locally, constants.inc.php will look like this:
As we develop, we’ll add more to this file.
Creating a PDO Object
Next, we want to create a connection so that our application can communicate with our database. This file will reside in the common folder along with the header, footer, and sidebar files. This file will create a database connection using PDO (PHP Data Objects). as well as setting up a couple other site-wide features: error reporting and opening a session.
The file will look like this when all’s said and done:
Because we’re in the development stage, we want to see any and every error that occurs on the site. By setting error_reporting() to E_ALL and changing the display_errors directive to 1 using ini_set() . we ensure that even notices will be displayed, which will keep our code cleaner and more secure.
Next, we use session_start() to start a PHP session. This will allow our users to stay logged in when we build that functionality later.
Finally, weinclude config.inc.php and create a PDO object using the constants defined within it. Note the use of the try-catch statement—this gives us the ability to use Exceptions. which help improve error handling. In this case, if the database connection fails, we’re simply going to output the error message.
The reason we’re using PDO for this project is because of its support for prepared statements , which virtually eliminates the risk of SQL injection. There are other options that allow prepared statements, such as the MySQLi extension. However, PDO is not database-specific, so migrating the app to Oracle or PostgreSQL wouldn’t require a full rewrite of our code.
Also, having used both MySQLi and PDO in projects, it’s just my personal preference to use PDO. Feel free to use whatever method of connecting to the database you prefer, but keep in mind that all database interactions in this exercise are assuming the use of PDO, and as such will probably require some reworking to accommodate your changes.
Framing Out a User Interactions Class
As we discussed in Part 2 of this series, we’ll be taking the object-oriented approach with this app. All of these actions will be contained within our ColoredListsUsers class. We’ll also need to create several files that will display information to the user and interact with the class, which we’ll cover as we get to them.
Building the Class
To get started, we need to create the file class.users.inc.php to contain the PHP class, which we’ll place in the inc folder.
With the file created, let’s build the skeleton of the class:
Connecting the Class to the Database
Before our class can do much of anything, it needs to have access to the database object we created in base.php. Our database connection within the object will be stored in a private property called $_db. and this property will be set by the class constructor. which will accept the instance of PDO created in base.php as an argument. If no instance of PDO is passed, one will be created by the constructor.
This ends up looking like this:
Now we are able to create an instance of our ColoredListsUsers object and use it to communicate with our database. Next, let’s start building user interactions!
Creating an Account
First and foremost, a user needs to be able to create an account. This will give them access to the rest of the site’s functionality.
As it stands, when a user visits our app, they’re greeted with our “sales” page, which encourages them to click the “Sign Up” button in the top right of their screen:
The home screen of our app
Clicking that “Sign Up” button directs the user to /signup.php —our first order of business should probably be to build that page.
Creating the Sign-Up Form
In our app’s root directory, create a file called signup.php and place the following code inside:
To start, we include our common/base.php and common/header.php files. Also, notice that we’re declaring a variable called $pageTitle just before we include the header. Remember in Part 4 when we built the header file and left that comment in the title tag?
We’re going to replace that with a snippet of PHP that reads:
That gives us the opportunity to post a different title for each page of our app.
With the proper files included, we can then create our sign-up form. The form will submit to signup.php —itself—so we need to place an if-else check to see if the form has been submitted. If so, we create a new ColoredListsUsers object and call the createAccount() method (which we’ll write in the next section).
Finally, we close the if-else statement and include the footer. Our sign-up page should look like this:
The sign-up page.
Notice the use of alternative syntax for the if-else statement. Normally, I don’t like to use this format, but in the case of outputting HTML, I prefer the way it ends with endif; instead of a closing curly brace (> ), which helps with readability in the script.
Saving the User’s Email Address
With our sign-up form ready, we need to write the createAccount() method that will be called when a user submits the form. This method will be public. Let’s go back to inc/class.users.inc.php and declare this method:
This method follows several steps to create an account: first, it retrieves the posted email address from the form (stored in the $_POST superglobal ) and generates a hard-to-guess verification code (the SHA1 hash of the current timestamp); second, it makes sure the supplied email address isn’t already in use; third, it generates and sends a verification email to the user with instructions on how to verify their account (we’ll define the method that does this in the next section); fourth, it stores the email address and verification code in the database; and finally, it creates a list for the user.
Each of these steps is monitored, and if any of them should fail, a specific error message is generated. Upon success, a message is generated to let the user know they should expect an email.
Generating and Sending a Verification Email
When the user creates an account, we need to send them an email with a link that will confirm their account. This is a precautionary measure that proves the user provided a real email address that they have access to and prevents a ton of spam accounts from being created easily.
To send the email, we’ll be using the built-in mail() function. In inc/class.users.inc.php. create the private sendVerificationEmail() method by inserting the following code:
coloredlists.com/accountverify.php?v=$ver&e=$e. This linksends the user to our app’s account verification file (which we’ll write in the next step) and sends the user’s hashed email address along with their verification code in the URI. This will allow us to identify and verify the user when they follow the link.
Verifying the User’s Account
After our user follows the verification link in the email, we need to check that their email and verification code are valid, and then allow them to choose a password. After they choose a password, we need to update the database to reflect the user’s new password, as well as setting the account’s status to verified.
First, let’s create a new file called accountverify.php in the root level of our app. Inside, place the following code:
Verifying the User’s Email and Verification Code
Before we can allow our user to select a password, we need to make sure that their account exists, that their email matches their verification code, and that their account is unverified. To do that, we need a new method in inc/class.users.inc.php called verifyAccount() :
This method executes a query that loads the user name stored in the database with the verification code, hashed user name, and a verified status of 0. If a user name is returned, login credentials are stored. This method returns an array with an error code in the first index, and a message in the second. The error code 0 means nothing went wrong.
Updating the User’s Password and Verified Status
Once the user has selected a password and submitted the form, the if-else statement will catch the verification code sent using the POST method and execute the updatePassword() method. This method needs to set the account status to verified and save the user’s hashed password in the database. Let’s build this method in ColoredListsUsers :
Finally, since verifying an account logs a user in, we need to update common/header.php to recognize that a user is logged in and display different options. In Part 4. common/header.php featured a code snippet that looked like this:
To make those comments into functional code, we need to modify this snippet with an if-else block:
Notice that we store in the session both the user name ($_SESSION['Username'] ) and a flag that tells us if the user is logged in ($_SESSION['LoggedIn'] ).
Next, let’s build the login form and allow our user to log in. To start, let’s create a new file named login.php at the root level of our app. Like our other publicly displayed files, this will include the base and header files. Then it checks if a user is already logged in, if the login form was submitted, or if the user needs to log in.
If logged in, the user is notified of this fact and asked if he or she wishes to log out.
If the form has been submitted, a new ColoredListsUsers object is created and the accountLogin() method is called. If the login succeeds, the user is directed to the home page, where his or her list will appear; otherwise, the login form is displayed again with an error.
If neither of the previous conditions exists, the login form is displayed.
Finally, the sidebar ads and footer are included to round out the file.
When the file is all put together, it should look like this:
Notice the “Did you forget your password?” links — we’ll be building this functionality a little later on in the article.
Building the Login Method
Now we need to build the accountLogin() method. This method will compare the supplied user name and the MD5 hash of the supplied password to verify that there is a matching pair in the database. If a match is found, the user’s name and a login flag are stored in the session and the method returns TRUE. If no match is found, the method returns FALSE .
Build this method in ColoredListsUsers by inserting the following code:
Next, our user needs to be able to log out. This is as easy as destroying the login data stored in the session and sending the user back to the login page.
Create a new file named logout.php at the root level of the app and place the following code inside:
Modifying Account Information
Next, we need to allow our users to modify their account information. In order to do that, we need to provide an “Account” page that will give them options to change their user name or password, as well as the option to delete their account.
Create a file named account.php at the root level of the app. There’s a lot going on here because we’re essentially combining three app functions within one file.
First, we include the base file and check that the user is logged in. If not, he or she gets sent out to the main page.
If the user is logged in, we check if any actions have already been attempted and assemble the corresponding success or failure messages if any are found.
Then we load the user’s ID and verification code using the method retrieveAccountInfo() and build three forms: one to update the user name (which is an email address, remember), one to change the account password, and one to delete the account.
Finally, we include the sidebar ads and the footer. Altogether, the file should look like this:
Creating the Method to Retrieve Account Info
In order to have the user’s login name and verification code available to our account option forms, we need to build a new method that will load this information from the database. In inc/class.users.inc.php. create a new method in ColoredListsUsers called retrieveAccountInfo() and add the following code:
Building the Interactions File
In account.php. all three forms direct to a file called db-interaction/users.php when submitted. This file helps relieve some of the clutter in account.php by determining form actions, creating a ColoredListsUsers object, and calling the appropriate methods to handle the action.
This file will be placed in a new folder called db-interaction. and it will be named users.php. Place the following code in the new file:
Updating the Email Address
When a user submits a request to change their email address, the method updateEmail() is called. This function simply executes a query that changes the email address associated with an account. It returns TRUE if the email is successfully changed, and FALSE otherwise.
Updating the Password
Quite similarly to updateEmail(). updatePassword() is called if the user submits a request to change their password. The only difference in the methods is that this one will compare the password and the password confirmation to make sure they match before saving.
Deleting the Account
If the user wants to delete their account, we need to go through several steps. First, we need to double-check that the user is logged in, because we certainly don’t want any accidental account deletions. If the user is logged in, we then delete their list items. If the list items are successfully deleted, we move on to delete the user’s lists. Finally, if the lists are successfully deleted, we delete the user from the database, destroy their session information, and send them to a page called gone.php , which we’ll build in a minute.
The method, when it’s all written, will look like this:
Resetting an Account Password
At this point, we’re almost done. The last thing we need to do is allow a user to reset a forgotten password. To do this, we need to create the file password.php at the root level of our app and place the following code inside:
When a user visits this page, they’ll be able to enter their email address. Submitting the form will return the account to unverified and send the user an email with a link to reset their password.
Returning the Account to “Unverified” Status
When the form in password.php is submitted, the information is sent to db-interaction/users.php and the resetPassword() method is called before sending the user to resetpending.php .
The resetPassword() method sets the verified field of our user’s database entry to 0. then calls the sendResetEmail() method.
Building the Reset Pending Page
After the user’s account is back in an unverified state and the email has been sent with their password reset link, we send them to resetpending.php to let them know what their next steps are. Create this file at the root level of the app and insert the following:
Generating a “Reset Password” Email
The sendResetEmail() method is very similar to the sendVerificationEmail() method. The main difference here is that the link sent to the user directs them to a page called resetpassword.php where they’re able to choose a new password.
Resetting the Password
Our very last step in this part of the app is to create the file resetpassword.php in the root level of the site. This file is very similar to the accountverify.php file we created earlier. After including the base and header files, it checks if the user is just arriving from their reset email.
If so, we are able to use the verifyAccount() method we wrote earlier to ensure that their credentials are correct. After verifying their credentials, we display a form that allows them to choose a password and confirm it.
After submitting the form, our script will fire the updatePassword() method we created earlier to save the new password. Then we redirect the user to account.php. where they’re shown a confirmation message letting them know that their password was changed.
Inside resetpassword.php. add the following code:
This article covered a whole lot of ground, and I went over some of it pretty quickly. Please don’t hesitate to ask for clarification in the comments!
In the next part of this series, our front-end designer will use some dummy lists to create AJAX effects. After he’s finished with the dummy lists, we’ll explore how to combine those AJAX effects with our back-end and build the list interactions class in part 7.