Creating Your First PHP Application: Part 3

In part 1 and part 2 we built the necessary classes, created a database table for our users and made a global.inc.php file that will act as a bootstrap on every page.

What’s Next

We’re now ready to build the front end pages. Bear in mind that everything you see here can be expanded and improved upon. For the purposes of this tutorial I’ve kept things relatively simple. For some suggested improvements, check out the “Extra Credit” section at the end of the post.

User Registration Page (register.php)

There are two parts to this page. A block of PHP at the top and the HTML at the bottom. As you develop your website, you may find that you’ll organize the code differently, but for clarity’s sake I kept it simple for this tutorial.

The PHP at the top loads the bootstrap (global.inc.php). It also contains the code that will be used for the form validation. The HTML at the bottom contains a simple registration form. A more detailed explanation can be found following the code.

The Code

<?php
//register.php

require_once 'includes/global.inc.php';

//initialize php variables used in the form
$username = "";
$password = "";
$password_confirm = "";
$email = "";
$error = "";

//check to see that the form has been submitted
if(isset($_POST['submit-form'])) { 

	//retrieve the $_POST variables
	$username = $_POST['username'];
	$password = $_POST['password'];
	$password_confirm = $_POST['password-confirm'];
	$email = $_POST['email'];

	//initialize variables for form validation
	$success = true;
	$userTools = new UserTools();

	//validate that the form was filled out correctly
	//check to see if user name already exists
	if($userTools->checkUsernameExists($username))
	{
	    $error .= "That username is already taken.<br/> \n\r";
	    $success = false;
	}

	//check to see if passwords match
	if($password != $password_confirm) {
	    $error .= "Passwords do not match.<br/> \n\r";
	    $success = false;
	}

	if($success)
	{
	    //prep the data for saving in a new user object
	    $data['username'] = $username;
	    $data['password'] = md5($password); //encrypt the password for storage
	    $data['email'] = $email;

	    //create the new user object
	    $newUser = new User($data);

	    //save the new user to the database
	    $newUser->save(true);

	    //log them in
	    $userTools->login($username, $password);

	    //redirect them to a welcome page
	    header("Location: welcome.php");

	}

}

//If the form wasn't submitted, or didn't validate
//then we show the registration form again
?>

<html>
<head>
	<title>Registration</title>
</head>
<body>
	<?php echo ($error != "") ? $error : ""; ?>
	<form action="register.php" method="post">

	Username: <input type="text" value="<?php echo $username; ?>" name="username" /><br/>
	Password: <input type="password" value="<?php echo $password; ?>" name="password" /><br/>
	Password (confirm): <input type="password" value="<?php echo $password_confirm; ?>" name="password-confirm" /><br/>
	E-Mail: <input type="text" value="<?php echo $email; ?>" name="email" /><br/>
	<input type="submit" value="Register" name="submit-form" />

	</form>
</body>
</html>

What It’s Doing

The HTML portion of the code should be relatively straight forward. The form action is set to register.php with the method being post. This means that when the form is submitted, register.php will be loaded again and the values in the fields will be sent in the $_POST variable.

The value of each input field is set to a PHP variable ($username, $password, etc). If the form hasn’t yet been submitted, all the values will be an empty string. If the form has been submitted and did not validate, those variables will contain the values from the previous submission of the form so that they do not need to be filled in again.

Additionally, if the form has been submitted and did not validate with the PHP code above, then the $error variable will be displayed. This variable will contain the reasons why the form did not validate.

The form validation is fairly straightforward as well. The $_POST variable is an associative array of variables passed to the current script via the HTTP POST method. Each form field’s value can be accessed in $_POST by using the name of the field as the key. The first thing we do is check to see if the submit button has been press (i.e. the form has been submitted). We check $_POST['submit-form'] with the isset() PHP function since “submit-form” was the name of the submission button on the form.

Once we know the form has been submitted, we can validate it. We’ll be using the UserTools class we created in part 2 to check to see if someone has already chosen the submitted username. If so we’ll flag the form as unvalidated by setting $success to false and we’ll describe the error in $error. The next step is to check to see if the passwords match using a simple comparison.

If the form validation was successful, we’ll put the information in an associative arrray called $data and use that array to create a new User object. We’ll they call the save() function of that User object with the $isNewUser flag set to true. We then log them in using our login() function (found in the UserTools class) and redirect them to welcome.php.

Here is some example code you might use for welcome.php:

<?php
//welcome.php

require_once 'includes/global.inc.php';

//check to see if they're logged in
if(!isset($_SESSION['logged_in'])) {
	header("Location: login.php");
}

//get the user object from the session
$user = unserialize($_SESSION['user']);

?>

<html>
<head>
	<title>Welcome <?php echo $user->username; ?></title>
</head>
<body>
	Hey there, <?php echo $user->username; ?>. You've been registered and logged in. Welcome! <a href="logout.php">Log Out</a> | <a href="index.php">Return to Homepage</a>
</body>
</html>

Login and Logout Pages

login.php

Much like register.php, login.php will have form validation at the top and the HTML login form at the bottom. The form is just two fields, username and password. The form validation calls the UserTools login() function and redirects them to index.php if login() returns true and displays an error if login() returns false. Very simple and easy. Here’s the code:

<?php
//login.php

require_once 'includes/global.inc.php';

$error = "";
$username = "";
$password = "";

//check to see if they've submitted the login form
if(isset($_POST['submit-login'])) { 

	$username = $_POST['username'];
	$password = $_POST['password'];

	$userTools = new UserTools();
	if($userTools->login($username, $password)){
		//successful login, redirect them to a page
		header("Location: index.php");
	}else{
		$error = "Incorrect username or password. Please try again.";
	}
}
?>

<html>
<head>
	<title>Login</title>
</head>
<body>
<?php
if($error != "")
{
    echo $error."<br/>";
}
?>
	<form action="login.php" method="post">
	    Username: <input type="text" name="username" value="<?php echo $username; ?>" /><br/>
	    Password: <input type="password" name="password" value="<?php echo $password; ?>" /><br/>
	    <input type="submit" value="Login" name="submit-login" />
	</form>
</body>
</html>

logout.php

Logging a user out is even simpler than logging them in. This page needs no HTML. It just logs them out using the logout() function we put in the UserTools class and redirects them back to index.php. Here’s the code:

<?php
//logout.php
require_once 'includes/global.inc.php';

$userTools = new UserTools();
$userTools->logout();

header("Location: index.php");

?>

User Settings Page

A registered user that is logged in may want to change their settings. To keep this example simple, we’re only going to allow them to change their email address. You may want to try and expand this to enable a user to change their password.

Much like our register.php and login.php pages, there will be an HTML section with the form and a PHP section containing the form validation and other vital PHP operations. In this case, when the form is submitted we’ll get the current user as a User object from their session and set the email attribute equal to the new email. We then simple call the save() function in the User class and the desired result is achieved.

The Code

<?php 

require_once 'includes/global.inc.php';

//check to see if they're logged in
if(!isset($_SESSION['logged_in'])) {
	header("Location: login.php");
}

//get the user object from the session
$user = unserialize($_SESSION['user']);

//initialize php variables used in the form
$email = $user->email;
$message = "";

//check to see that the form has been submitted
if(isset($_POST['submit-settings'])) { 

	//retrieve the $_POST variables
	$email = $_POST['email'];

	$user->email = $email;
	$user->save();

	$message = "Settings Saved<br/>";
}

//If the form wasn't submitted, or didn't validate
//then we show the registration form again
?>

<html>
<head>
	<title>Change Settings</title>
</head>
<body>
	<?php echo $message; ?>

	<form action="settings.php" method="post">

	E-Mail: <input type="text" value="<?php echo $email; ?>" name="email" /><br/>
	<input type="submit" value="Update" name="submit-settings" />

	</form>
</body>
</html>

The Final File – index.php

With index.php, the sky is the limit. Since this tutorial was mostly about setting up a very “bare-bones” app, I’ll leave this mostly to your creativity. To get you started, here’s some basic code that shows links to “login” or “register” if the user is logged out and shows links to “logout” or “change settings” if the user is logged in.

<?php
//index.php 

require_once 'includes/global.inc.php';
?>

<html>
<head>
	<title>Homepage</title>
</head>
<body>

<?php if(isset($_SESSION['logged_in'])) : ?>
	<?php $user = unserialize($_SESSION['user']); ?>
	Hello, <?php echo $user->username; ?>. You are logged in. <a href="logout.php">Logout</a> | <a href="settings.php">Change Email</a>
<?php else : ?>
	You are not logged in. <a href="login.php">Log In</a> | <a href="register.php">Register</a>
<?php endif; ?>

</body>
</html>

Extra Credit / Taking it Further

Because this tutorial is admittedly basic I’ve come up with a list of thing you may want to improve upon on your own.

  • Error handling in each of the classes
  • Protection against malicious form submissions and sql injection
  • Implementing the PHP singleton pattern for the DB class
  • Use include() to build a template
  • Add a “remember me” check box that utilizes cookies to keep the user logged in
  • Configure include_path in php.ini or with ini_set() for easier inclusion of files in different directories

Further Reading

As you become more familiar with OOP and PHP, here are some suggestions for developing quality applications:

Final Words

I hope you’ve enjoyed this tutorial. A zipped folder of the entire project is available for your downloading pleasure. Simply set up your database, configure DB.class.php with your database settings, and put the contents of the zip in your root folder.

  • Stumble It!
  • Bookmark It!
  • Tweet it!

About Brian Muse

Brian is a computer engineer and web developer from MA. He's the lead developer of yourather.com and heads up development at One Mighty Roar. He also blogs about home computer setups at desktopped.com. On twitter @briancmuse.

 

Discussion

  1. Nick Parsons

    December 14th, 2009 at 2:35 PM

    This has been an excellent set of tutorials, Brian! Although it is real basic (like you said), you did a great job putting together a good, clear explananation to get someone started.

    I like the fact that you walked through all the organization and setup, not just the actual coding like a lot of tuts do. Great work!

  2. Destiny Islands

    December 14th, 2009 at 8:35 PM

    There are so many great PHP tutorials out there on the web, it’s almost impossible not to understand PHP by now as a web developer!

  3. Rockstyle

    December 15th, 2009 at 6:57 AM

    Great tutorial, looking forward to see more. Would be nice if you made some series about theming (theming like in wordpress – files) clean html instead of echoing, this would be really great. I actually don’t see download link to get all the project files, could you fix this?

  4. Sérgio Soares

    December 15th, 2009 at 11:31 AM

    Nice tutorial. Awesome series.
    Could u add the source code, i’m having problems with my application on login step.
    thanks

  5. Austin

    December 16th, 2009 at 9:32 PM

    Oh, there we go. The singleton pattern is what I was looking for. I understand things now. :)

    Pretty much disregard my comment on the last post. Thanks, and great tutorials!

  6. Zach Dunn

    December 20th, 2009 at 12:14 PM

    I’ve updated the post to include source files. You can also download them through this link.

  7. Shrinivas

    December 30th, 2009 at 7:05 AM

    Well written and explained article, I’m pointing guys looking to begin with php+mysql to this set of tutorials. Thanks!

  8. Brandon

    December 30th, 2009 at 3:12 PM

    Thank you for the tutorials. I am new to OOP and php classes.

    Question: Why would the error handling to be inside the UserTools class?

    Thanks for your help.

  9. Brandon

    December 30th, 2009 at 3:14 PM

    Correction to my question:

    Why would the error handling not be inside the UserTools class?

    Thanks again!!

  10. nightmare

    December 31st, 2009 at 3:17 AM

    The installation process I encountered this error:
    http://hitupload.net/files/errorphp.jpg
    Please help !!

  11. thorkon

    January 26th, 2010 at 11:41 AM

    I get an error “unserialize() expects parameter 1 to be string, object given in includes/global.inc.php on line 20″.

    How can I get rid of it / what’s wrong?

  12. Zack

    February 18th, 2010 at 3:40 AM

    I’ve got the same error as thorkon. And two more error later:

    Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in C:\AppServ\www\cms\classes\DB.class.php on line 42

    Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in C:\AppServ\www\cms\classes\DB.class.php on line 25

  13. Zack

    February 22nd, 2010 at 12:11 AM

    I found that, after login, page redirects to index.php, after the unserialize was run, all the SESSION settings($_SESSION['user'], $_SESSION['logged_in'], $_SESSION['login_time']) will change to numbers, so that if you run change email page, or logout, the unserialize() function gets error.

    But I am not sure what causes this, is it about the unserialize() function?

  14. Tao

    March 5th, 2010 at 7:35 AM

    I had the same problem and solved it by putting an “php.ini” file on the app folder (together with the front end files) containing only “register_globals = off”.

    (thanks Brian Muse for your assistance!)

  15. Brian Muse

    March 5th, 2010 at 7:43 AM

    @Tao and others
    Register globals is most likely your problem, as Tao pointed out. This ini directive was turned on by default for versions of PHP below 4.2. Since 4.2.0 it has been turned off by default and using it is highly discouraged.

    In fact, it is being completely removed in PHP 6.0.

    Learn more here: http://www.php.net/manual/en/ini.core.php#ini.register-globals

Join the Conversation!

Remember: Life's not all doom and gloom, so please keep it constructive. If we've made an error or missed something big, please let us know! Learning is revisions, after all.

CommentLuv is Enabled

 

Sponsors

Advertise on Build Internet!