By Paul McFedries

Before your web app is usable, you’ll need set up the back end to handle users. Most web apps that manage users need to implement at least the following tasks:

  • Signing up new users: Includes not only capturing the user’s email address (to use as a username) and password, but also sending out a verification email to make sure the user isn’t a bot or spammer
  • Signing in users: Enables each user to access her own data
  • Signing out users: Prevents others from accessing a user’s account when his computer is left unattended
  • Updating user data: Enables each user to change her password and to reset a forgotten password
  • Deleting users: Enables a user to remove his account and data from the server

Here’s the bird’s-eye view of what you’ll be doing:

  1. Build a class for handling user interactions. That class includes one method for each of the preceding tasks.
  2. Provide the user with an interface for signing up, signing in, signing out, modifying account data, and deleting the account.
  3. To start processing a user task, set up an event handler for each account-focused interface element. If you’re using a sign-in form, for example, then you might set up a submit event handler for that form.
  4. Use each event handler to send the form data to a single PHP script via Ajax. Importantly, that form data includes the value of a hidden field that specifies the type of “user verb” being performed (sign up, sign in, reset password, and so on).
  5. In the PHP script, create a new object from the class of Step 1, check the user verb sent by the Ajax call, and then call the corresponding class method. For example, if the event is signing up a new user, the script would call the class method that handles creating new user accounts.

Starting the web app’s user class

The class for your web app’s users needs to do at least the following three things:

Accept a parameter that references the current MySQLi object.

  • Define a method for each of the user verbs.
  • Define any helper functions required by the user verbs.
  • With these goals in mind, here’s the skeleton class file:
<?php
class User {

  // Holds the app’s current MySQLi object
  private $_mysqli;

  // Use the class constructor to store the passed MySQLi object
  public function __construct($mysqli) {
    $this->_mysqli = $mysqli;
  }

  // Here are the user chores we need to handle
  public function createUser() {

  }
  public function verifyUser() {

  }
  public function signInUser() {

  }
  public function sendPasswordReset() {

  }
  public function resetPassword() {

  }
  public function getDistanceUnit() {

  }
  public function updateDistanceUnit() {

  }
  public function deleteUser() {

  }
}
?>

The class declares the private property $_mysqli, which it uses to store the current instance of the MySQLi object (created earlier in the initialization.php script). Store this file in private/classes/user_class.php.

To create an instance of this class, you’d use a statement similar to the following:

$user = new User($mysqli);

Creating a user handler script

The various user verbs will be initiated via Ajax calls to a single PHP script. Each Ajax call needs to specify the user verb required, and the PHP code routes the request to the corresponding method in the User class.

Here’s the PHP script, which you can save as public/handlers/user_handler.php:

<?php
  // Initialize the app
  include_once '../../private/common/initialization.php';
 
  // Include the User class
  include_once '../../private/classes/user_class.php';
 
  // Initialize the results
  $server_results['status'] = 'success';
  $server_results['control'] = '';
  $server_results['message'] = '';
 
  // Make sure a user verb was passed
  if (!isset($_POST['user-verb'])) {
    $server_results['status'] = 'error';
    $server_results['control'] = 'form';
    $server_results['message'] = 'Error: No user verb specified!';
  }
  // Make sure a token value was passed
  elseif (!isset($_POST['token'])) {
    $server_results['status'] = 'error';
    $server_results['control'] = 'form';
    $server_results['message'] = 'Error: Invalid user session!';
  }
  // Make sure the token is legit
  elseif ($_SESSION['token'] !== $_POST['token']) {
    $server_results['status'] = 'error';
    $server_results['control'] = 'form';
    $server_results['message'] = 'Timeout Error! Please refresh the page and try again.';
  }
  // If we get this far, all is well, so go for it
  else {
   
    // Create a new User object
    $user = new User($mysqli);
   
    // Pass the user verb to the appropriate method
    switch ($_POST['user-verb']) {
     
      // Sign up a new user
      case 'sign-up-user':
        $server_results = json_decode($user->createUser());
        break;

      // Sign in an existing user
      case 'sign-in-user':
        $server_results = json_decode($user->signInUser());
        break;

      // Send a request to reset a user's password
      case 'send-password-reset':
        $server_results = json_decode($user->sendPasswordReset());
        break;

      // Reset a user's password
      case 'reset-password':
        $server_results = json_decode($user->resetPassword());
        break;

      // Get the user's distance unit
      case 'get-distance-unit':
        $server_results = json_decode($user->getDistanceUnit());
        break;

      // Update distance unit
      case 'update-unit':
        $server_results = json_decode($user->updateDistanceUnit());
        break;

      // Delete a user
      case 'delete-user':
        $server_results = json_decode($user->deleteUser());
        break;

      default:
        $server_results['status'] = 'error';
        $server_results['control'] = 'token';
        $server_results['message'] = 'Error: Unknown user verb!';
    }
  }
  // Create and then output the JSON data
  $JSON_data = json_encode($server_results, JSON_HEX_APOS | JSON_HEX_QUOT);
  echo $JSON_data;
?>

After initializing the app by including initialization.php, the code also includes the User class file. The code then sets up an array named $server_results, which holds the results that the script sends back to the front end:

  • $server_results['status'] will be either success or error.
  • $server_results['message'] holds the success or error message to display.

The code next runs through a series of checks: making sure a verb was passed, making sure a token value was passed, and then comparing that token value with the session token. If the code gets past those tests, a switch() statement runs through the possible values for $_POST['user-verb'] and calls the corresponding User method.