Pages

Banner 468

Tuesday 3 May 2011

Building a Web Space Management System - 3

0 comments
 
Last week I mentioned that I wasn't to happy with the way the code was structured so far. It was untidy to say the least and hard to maintain, even at this early stage. I also said that I was looking into MVC and OOP to instill some sense of structure and order to the project. We have a saying in Maltese that translates to: "the sauce will cost you more than the fish it's meant to garnish". Writing even a simple MVC framework for this project would have been massive overkill and would have taken too much time and effort for something that is not meant for production. Of course there are PHP frameworks out there that support MVC but using existing frameworks is beyond the scope of this blog.

However, I wasn't giving up. I still wanted to improve the way the code was written so I turned to good old Object Oriented Principles (OOP) and some other nifty tricks I picked up on the net while doing my research to help me turn my spaghetti code into neatly layered lasagne!

I wanted to spend just a little bit of time on how I re-structured the code I had so far before going further, as all the new stuff I added is obviously based on these changes. You will also notice changes in the look and feel of the app (being a UX buff I couldn't resist :) and the name (I've changed everything else so why not!).

1. Introducing Objects

Up to now we have functionality that allows users to register and log-into our system, and this sentence alone screams "UserAccount Class". My UserAccount class is structured as follows:

Properties

  • username
  • password
  • email
  • errors()  - an array that stores any errors thrown by the class
  • salt         - a random set of characters that are appended to the user's password before hashing it to improve security
Methods

  • login - accepts a username and password as arguments and handles authentication
  • register - attempts to register the user
  • isUsernameAvailable - private method used during registration to check whether the chosen username is unique or not.
The code in the UserAccount class methods was extracted from the login and registration pages.  This code remained largely intact, with only minor modifications required to suit the class.

I also added a small FormValidator class to handle common validations such as comparing strings (used in the registration form to confirm the user's password choice).

2. Re-structuring the Pages

With the authentication and registration code safely encapsulated in the UserAccount class, the login and registration pages became simpler. So much so that I decided to merge them into one page. The login page now contains two forms: the login form and the registration form. These forms post to the "processlogin.php" and "processreg.php" scripts respectively. These scripts contain all the calls to the UserAccount class that handle authentication and registration. Placing this code in these script files separates server-side code from the HTML which is exactly what I want. I also placed php code that is common to all pages (such as session management and database connection) in another script called "shared.php". Here's the code for the "shared.php" and "processlogin.php" scripts:

<?php
   define ('DS', DIRECTORY_SEPARATOR);
   define ('ROOT', dirname(dirname(__FILE__)));
   define ('MaxFiles', 3);

   include_once (ROOT.DS."lib".DS."dbconfig.php");

   function __autoload($className) {
      if (file_exists(ROOT . DS . 'lib' . DS . strtolower($className) . '.php')) {
         require_once(ROOT . DS . 'lib' . DS . strtolower($className) . '.php');
      } else {
         /* Error Generation Code Here */
      }
   }

   mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);      
   mysql_select_db("db_webspace");

   session_start();


The shared.php script defines constants for the root folder of our website and the directory separator. The latter is useful because of the fact that Windows and Linux have different directory separators (backslash and forwardslash) so it makes our code slightly more platform independent which is nice. The scripts also makes use of the __autoload function in PHP to make sure that class files (such as our UserAccount.php) are "automagically" loaded whenever they are needed, which is pretty handy. It also connects to the database and starts the session. I've stripped all the error handling code from the script for simplicity's sake, but obviously there is some to handle those annoying exceptions.

The "processlogin.php" script below is called when posting the login form. In a nutshell, it reads the values for the username and password from the $_POST associative array and after making sure the values are not blank, it creates an instance of the UserAccount class and attempts authentication. If all is successful the script sets session variables to indicate that the user has been authenticated and re-directs to the main application page. If not, the login page is included so that the error messages can be displayed to the user.

<?php // processlogin.php
   include_once ('./lib/shared.php');
   $errMsg = "";
   
   if ($_POST['txtUname'] != "" && $_POST['txtPassword'] != "") {
      $User = new UserAccount ();
  
      if (!$User->login($_POST['txtUname'], $_POST['txtPassword'])) {
         $errMsg = 'Incorrect Username or password';
      }
   } else {
      $errMsg = "Please enter a username and password";  
   }

   if ($errMsg != "") {
      include 'login.php';
   } else {
      $_SESSION['loggedin'] = 1;
      $_SESSION['user'] = $User;
      header('Location: .' . DS . 'space' . DS . 'main.php');
      die();
   }


You may notice that in both these scripts, since they solely contain PHP code, the closing PHP tag "?>" was left out. This is purposely done to prevent any whitespace from being unintentionally sent into the response.

Here's what the combined login and registration page looks like:


3. The Web Space Manager


Past the login and into the 'private' area of the site which I refer to as the 'Web Space Manager'. I wanted a single interface through which users could browse through the files and folders of their web space, upload new files and see how much free space they had left. I also wanted to allow users to create folders in their space and delete unwanted files.  Quite a lot to do, so I want to dedicate the next post to describe how I went about it, in the meantime here's a little screenshot of the space manager page (still needs polishing up).


4. Final Thoughts

Although going back and restructuring the pages took some time and effort, the end result was definitely worth it.  The entire exercise helped me understand more how PHP works and how to get more out of it which after all is the whole point of this project.  I also picked up some nifty tips & tricks while going through countless articles on the web, which is always good.

Leave a Reply