How To: Code Your First Web App (Part 2)

In Part 1 of How To: Code Your First Web App, I covered the basics of setting up a MySQL database, connecting to it with PHP and then I introduced a few functions to create and manage users. At the end, I briefly went into setting up the header file which will be used with every file created from here on out. The next step is creating the main files that actually do things.

As mentioned in the comments of Part 1, copying and pasting the code doesn't always work due to the way quotes get mangled. Download the complete set of files at the end of this series.

With the completed header.php, I can progress to the actual index file. Here's what a basic index.php might look like:

<?php include('header.php'); ?>
<div id="header">
   <div class="login">
        < ?php //example of how to check for logged in user
        user = get_user();
        if(user !== NULL) { //if logged in
      	echo "Welcome " . user . ". ";
        } else {
	      echo 'Welcome guest.';
       } ?>

<div class="primary"> //whatever your web app actually does </div> //close primary

<?php include('footer.php'); ?>

That's very basic - just include the header file, do something, include the footer file. The easiest way to get user data and check to see if a user is logged in is with the get_user() function. The code within the login div echoes the logged in user's name to let them know they are logged in. Below is a simple footer.php file - it just basically closes out the body and html tags while holding a footer div for displaying whatever you'd like. Typically you would link to things like a privacy policy and TOS page.

    <div id="footer">
     My First Web App

Dynamic Menus

Now that there is a light framework, it's time to show you some easy ways to actually get your web app to do something and interact with the database. First off, I'm going to show you an easy way to alter a page menu depending on whether the user is logged in. For example, a user not logged in will only see a few page menu links while a logged in user would see specific links to their user account or settings pages.

I like to make a separate file for the menu and name it nav.php, short for navigation. This file is rather tame; it contains links to pages as well as code to check for the user's session and determine logged-in status.

user = get_user();
if(user !== NULL) { ?>
<!--following menu items shown if logged in-->
	<div id="nav">
	  <ul class="menu">
    	        <li class="<?php echo home; ?>"><a href="index.php" title="Home">Home</a></li>
    	        <li class="<?php echo account; ?>"><a href="account.php" title="Account">Account</a></li>
                <li class="<?php echo profile; ?>"><a href="profile.php" title="Profile">Profile</a></li>
		<li class="<?php echo logout; ?>"><a href="logout.php" title="Logout">Logout</a></li>
<?php } else { ?>
<!--following menu items shown if not logged in-->
	<div id="nav">
	  <ul class="menu">
    	        <li class="<?php echo home; ?>"><a href="index.php" title="Home">Home</a></li>
		<li class="<?php echo login; ?>"><a href="login.php" title="Login">Login</a></li>
	        <li class="<?php echo register; ?>"><a href="register.php" title="Register">Register</a></li>
<?php } ?>

Each list element has a class set to a PHP variable. That way, when you include nav.php in each file you can also specify something like home = current_page_item. If you had your CSS setup so that the tab with "li.current_page_item" was styled differently than the rest, you'd have a dynamic menu at your disposal. Alternatively, you could take a stab at integrating Matt's intelligent menu code.

To finish off my menu, simply add this chunk of code after the header div in each file or wherever you want the menu to appear. Be sure to change "home" to correlate to the page you're adding the code to. For example, if your nav.php had a list element with the class settings and you were placing this code on the settings page, change home in this code example to settings. This ensures that the settings page menu link is styled differently.

< ?php 
home = "current_page_item";

Registering Users

Adding users to the database will require a form to pass user input data to the database after a few input validations (confirming password, etc). Forms are an easy way of accepting user input and manipulating the database with only a few MySQL queries. As discussed in Part 1, the users table in the database keeps track of user name, password and email. Below is a form that can accept those values, it can be put on any page structured like the index.php skeleton I created above.

<form action="register_form.php" method="post">
<label for="user"><b>Username:</b></label> <input name="user" type="text" id="user" size="20"/><br />
<label for="password"><b>Password:</b></label> <input name="password" type="password" id="password" size="20"/><br />
<label for="password"><b>Confirm Password:</b></label> <input name="confirm_password" id="password" type="password" size="20"/><br />
<label for="email"><b>Email:</b></label> <input name="email" type="text" id="email" size="20"/><br />
<input type="hidden" name="action" value="create"/>
<input type="submit" id="submit" value="Register"/>

The first line establishes the form action as another file "form.php" - this is where the inputted data gets sent and processed. The labels come in handy when styling the forms with CSS as do the input ids. The type "password" for the password inputs displays text as dots. Then there is the input type submit which makes the button to send the inputted values to the actual form for processing. Let me pull up the form code..

user = make_safe(_POST['user']);
pwd = make_safe(_POST['password']);
confirmpwd = make_safe(_POST['confirm_password']);
email = make_safe(_POST['email']);
if(_POST[&#39;action&#39;] == &#39;create&#39;) {
	// creating a new account.
	// does account already exist?
            // make sure password matches the confirm password
	if(!user_exists(user) &amp;&amp; (pwd == confirmpwd)) {
		create_user(user, pwd, email); //make the user!
		do_login(user, pwd); //login
		header(&#39;Location: index.php&#39;);
		//redirect to homepage
	} else { //oh noes!
		error_message = &quot;Account creation failed!&quot;;
                    //this is outputted later in the form

In PHP, I can grab a data value passed on from a form is by way of _POST['INPUT_NAME']. Remember when I had the inputs and each one had its own name; user, password, email, etc? I just used that input name inside of _POST to grab that value. To protect against XSS exploits and follow basic PHP security, I passed each _POST value through my make_safe() function from functions.php and set it equal to a variable. I didn't have to set it equal to a variable, but it just makes things easier to digest. For more on basic PHP script security, look no further (oops that site no longer exists).

The real meat of the code comes with the "if(!user_exists(user) && (pwd == confirmpwd)) {" section. The loop ensures that the user does not already exist and that the user's password matches the confirmation password entered. Inside the loop I ran create_user(), passing it the required parameters and then logged in the user with do_login() after the user was created. The last step is redirecting the user somewhere useful with header('Location: index.php'). However, you might consider sending your new users to their account page to input additional info.

The final part of the loop creates an error message we can output if the user couldn't be created. It's probably a good idea to extend this code out and develop separate error messages if the passwords didn't match or if the user already exists in the database. Later in form.php, I echo the error message if it isn't null, which I set error_message to at the beginning of the file.

Logging In

Adding on to the form.php code, I can implement a loop to log the user in.

else if(_POST['action'] == 'login') {
		if(do_login(user, pwd)) {
			// user is logged in
			// redirecting user to somewhere useful
			header('Location: index.php');
		} else {
			error_message = "Username or password bad!";

Now you can point the following input fields to use form.php, as I demonstrated earlier with user registration.

<form action="form.php" method="post">
        <label for="user"><b>Username:</b></label> <input name="user" type="text" id="user" size="20"/><br />
	<label for="password"><b>Password:</b></label> <input name="password" type="password" id="password" size="20"/><br />
	<input type="hidden" name="action" value="login"/>
	<input type="submit" id="submit" value="Login"/>

Deleting Users

You guessed it, I'm going to use a form for this as well.

<form action="delete_account.php" method="post">
   <input type="submit" id="submit" value="Delete Account"/>
user = get_user();
deleteaccount = "delete from users where user='user'";

if (!mysql_query(deleteaccount)) { die('Error: ' . mysql_error()); } header('Location: index.php');

Wasn't that easy? I could have made it even easier if I had made a delete_user() function but you get the idea. In the code above, deleteaccount is a MySQL query that deletes from the users table wherever it finds a user that is equal to the current, logged-in user. You can also see where I have my die() debugging line output any errors that might crop up. Not shown was the inclusion of the standard things like util.php, functions.php, the IN_PHP define thing, xmysql_connect() and session_start(). Unlike the main page files, I can't include the header.php file on form files instead of doing all those things. That's because my header.php has some HTML in it and when doing PHP form stuff, PHP will choke and give an error along the lines of "headers already sent". You don't want to send out any data like HTML markup before you finish doing the form stuff. Also, without calling session_start(), the get_user() call will fail as there is no session id to use in get_user()'s MySQL command.

Logging Out

Logging a user out is one of the easiest things to accomplish. All I have to do is get the user to access the page below. The page destroys the user's PHP session, requiring that they log back in to be recognized as a valid user.

define('IN_PHP', true);

user = get_user(); do_logout(user); session_destroy(); //destroy the session! header('Location: index.php'); //back to the homepage you go ?>

The do_logout() function in functions.php replaces the user's session id in the users table with a blank value while session_destroy() ensures that PHP has forgotten about the session id as well.

I've got more to talk about so there will be a Part 3 as well.