PHP Tutorial

Step 9

PHP Tutorial

In this tutorial we will create a simple twitter copycat. In step 9 we will add some error handling to our registration form.

Step 9

1. We will start by giving the same treatment to the actions/user/register.php file as we have given the list_user.php file in the previous step. If any required parameter is missing we will redirect the user to the user registration form and add an error message to the error messages array.

if (!$_POST['username'] || !$_POST['realname'] || !$_POST['password']) {
  $_SESSION['error_messages'][] = 'All fields are mandatory';
  header("Location: $BASE_URL" . 'pages/users/register.php');
  exit;
}

2. This is not enough. We don’t want the user having to re-type the complete form because he made a mistake in one of the fields. So we have to send the values of all parameters received by our action back to the form. We will use another session array for this:

if (!$_POST['username'] || !$_POST['realname'] || !$_POST['password']) {
  $_SESSION['error_messages'][] = 'All fields are mandatory';
  $_SESSION['form_values'] = $_POST;
  header("Location: $BASE_URL" . 'pages/users/register.php');
  exit;
}

We are lazy so we are just sending the complete $_POST array back to the form.


3. We now have to fill our form with those values. This is the responsibility of the register.tpl template. In order to be as generic as possible we will pass the array containing these values to smarty in the init.php file. This way, we can reuse this mechanism with minimum effort. We should also delete the values after assigning them to smarty:

if (isset($_SESSION['form_values'])) {
  $smarty->assign('FORM_VALUES', $_SESSION['form_values']);
  unset($_SESSION['form_values']);
}

4. In the register.tpl template we just have to use insert these values into the correct input fields. We will of course ignore the password field:

<form action="{$BASE_URL}actions/users/register.php" method="post">
  <input type="text" name="realname"
         value="{if isset($FORM_VALUES)}{$FORM_VALUES.realname}{/if}"
         placeholder="Name">
  <input type="text" name="username"
         value="{if isset($FORM_VALUES)}{$FORM_VALUES.username}{/if}"
         placeholder="Username">
  <input type="password" name="password" value="" placeholder="Password">
  <label><input type="submit" value="Register"></label>
</form>

5. Sometimes errors are impossible to detect before trying to execute a query in the database. PDO has an exception handling mechanism that is disabled by default. To enable it, let’s add this line to our init.php file after connecting to the database:

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

6. Now we can catch any errors thrown by the database in our action page and do something about it. For example, instead of just calling the createUser function and hope everything goes according to plan, we could:

try {
  createUser($realname, $username, $password);
} catch (PDOException $e) {
  $_SESSION['error_messages'][] = 'Error creating user';
  $_SESSION['form_values'] = $_POST;
  header("Location: $BASE_URL" . 'pages/users/register.php');
  exit;
}

7. Instead of just sending a generic error to the user, we could send the complete error message like this:

$_SESSION['error_messages'][] = 'Error creating user: ' . $e->getMessage();

But this is exactly user friendly. We could, however, try to parse the error message and try to determine the cause of the error. For this example we’ll just scan the error message and look for the users_pkey string inside it. It’s up to you to find imaginative ways to parse the error message using PHP [String functions or Regular expressions:

if (strpos($e->getMessage(), 'users_pkey') !== false)
  $_SESSION['error_messages'][] = 'Duplicate username';
else $_SESSION['error_messages'][] = 'Error creating user';

You can find the complete code after step 9 here. In step 10 we will create the login and logout functionalities.