Re-inventing the Wheel
One of the most difficult tasks a PHP programmer faces is “fixing” a site built by another developer. Since I’m not a graphic designer, I try and keep the graphic design (typically stored in a CSS file) and use the customer’s goals to sketch out a class diagram of what needs to be accomplished. Sometimes I can find some little “PHP Gems” in the original developer’s code that can be incorporated into a class method, but for the most part, it’s easier and faster to dump the whole thing and re-start using OOP principles and design patterns. Often, a client will tell me “they just want a little change,” but usually a little change (e.g., “Make it work with mobile”) can cause unwanted consequences in unstructured code. The result is that the site crashes with the “little change.”
Recently, I had been asked to re-do a registration and log-in module. This turned out to be an interesting project because it’s something that most business and organizational sites require. The original log-in was a patch-work of snippets of code found online, and while some of it was fine, it was a mess structurally. This led me to consider the two dumbest pieces of advice in PHP programming:
PHP Dumb Advice 101:
- If it ain’t broke, don’t fix it.
- Don’t re-invent the wheel.
The first piece of dumb advice is the same as saying “Don’t improve it.” There’s nothing wrong looking for ways to improve a program for any number of reasons. The flexibility in OOP is designed so that you can improve and change code to make it better—add functionality, improve speed, or make it transportable. So just remember that while a horse worked just fine for transportation, a car works a lot better. The second dumb advice about not-reinventing the wheel means “Don’t look for better techniques.” A busy programmer who has to get a job done, yesterday!, will use the same old wheel just because she doesn’t have time to reinvent it. However, if you look at the history of the wheel, it just kept getting reinvented. OOP is a new kind of wheel.
It was with this attitude that I set about to make a basic registration module. I used the following conditions:
- Everything had to be a PHP object except the external CSS file
- Uses a MySql database
- A security class is kept separate from a registration class
- Checks for unique user names
- Registration object is never used before passing through security object
Before getting into the program, test it (click Play) and download the code:
Everything An Object
Every time I see an HTML and PHP code mix, I cringe. Yes, it works fine, but if you’re going to use HTML and PHP together, why not create a PHP object that you can use as an object, control the visibility of the properties and methods, and use interactively? In previous posts on this blog, you’ve seen heredoc strings used to wrap HTML code and assign that string to a private variable. This is easy to do; just write and debug the HTML, copy it all and dump it into a heredoc wrapper. So to begin, take a look at the following PHP class:
//RegisterUI.php
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors", 1);
function __autoload($class_name)
{
include $class_name . '.php';
}
class RegisterUI implements IUI
{
//Get the table name from constant in interface
private $bletchley=IUI::BLETCHLEY;
private $regUI;
public function __construct()
{
//Use the Security object to encode table
$sec=new Security();
$this->bletchley=$sec->doEncode($this->bletchley);
$this->regUI=<<
|
What I’m calling the “heredoc wrapper” refers to the portion of the code where the entire HTML5 document is “wrapped” in a heredoc string. The wrapper begins with the heredoc operator (<<<) and identifier (ALL CAPS) and terminates with the heredoc identifier followed by a semi-colon at the very beginning of a new line. In the RegisterUI class, the wrapper can be seen in a variable assignment that begins with,
$this->regUI=<<
and ends with,
REGISTER;
You can look at more posts on heredoc strings HERE and HERE and in the PHP Manual.
The important feature of wrapping HTML inside PHP classes is that you can do certain things with them that would be difficult or impossible with raw HTML. For example, as part of the class but outside of the REGISTER heredoc string are the lines:
private $bletchley=IUI::BLETCHLEY;
$this->bletchley=$sec->doEncode($this->bletchley);
Then, in the HTML line in the REGISTER string in the hidden form element,
bletchley>
you again see the private variable $this->bletchley. When you run the program, take a look at the HTML source code. Figure 1 shows what you will see:

Figure 1: Only code is visible in HTML Source
PHP’s interface structures are interesting in that while you cannot have any concrete methods stored in them; you can have constants, which must have assigned values. By placing the name of the table in the interface (IUI), it can first be encoded in the PHP class and then assigned as a value to a hidden form. So, even if the form is revealed in looking at the HTML source, the table’s actual name is hidden. The RegisterUI class implements the IUI interface. The interface itself is simple:
interface IUI
{
//Store name of table
const BLETCHLEY ="registered";
}
?>
|
As far as the user is concerned, all that he sees is the UI and a feedback window that lets him know whether his username and password are accepted or whether he has to try a different user name. Figure 2 shows this simple user interface:

Figure 2: User interface
The user just needs to see what she needs to register. The bare minimum in this example can be expanded, but to get started, it’s best to begin with just what we need and nothing more.
The Client Calls Security
With the user interface (UI) completed, the next step is to structure the design for following good OOP practices to accomplish a clear goal. This application has the following goals:
- Provides an entry point for uses to enter information.
- Checks the information to see if it is acceptable
- Either stores the information or informs the user that the user name must be changed
Figure 3 shows the class diagram for accomplishing these goals with the specific objects and operations:

Figure 3: Class diagram of registration project
Having completed the UI, the next step is to look at the Client class. In this case, Client takes the requests passed on from the user and processes them. The UI passes three superglobal values: username, password and secret. However, all the Client uses is the secreg which has been encoded; so essentially the Client takes the encoded table name and passes it on to Security. (Think of this process as the UI checking in at the airport and then the client moving you on to security where your secreg value is used as a passport.)
error_reporting(E_ALL | E_STRICT);
ini_set("display_errors", 1);
function __autoload($class_name)
{
include $class_name . '.php';
}
class Client
{
private static $useNow;
//client request
public static function request()
{
//Passes encoded tanble name to private static variable
self::$useNow=$_POST['secreg'];
$sec=new Security();
self::goGlobal($sec);
}
private static function goGlobal(ISecurity $secure)
{
$secure->doSuperGlobal(self::$useNow);
}
}
Client::request();
?>
|
The Client encapsulates both the property for the encoded table name ($useNow) and the method used to call the processing method of the Security class (goGlobal()). Note that the goGlobal() static method uses code hinting to force the requirement of the use of the ISecurity interface. (The ISecurity interface is an abstract class.)
Entering Security
In establishing an interface (abstract class in this case) for some kind of security module, I want to communicate the idea that before registration implement some kind of security. If you search the Web for either PHP security or software security in general, you will find dozens of ways to increase security—from using a highly secure web service to turning off error checking. The point is not to implement a specific type of security but rather have a separate place that does one thing: deal with security.
For this example, some very basic techniques are employed, and while they will help deter novice hackers, in no way should they be considered mechanisms that guarantee online security. First, in examining the ISecurity abstract class, you can see those with general flexibility and second, you can see their implementation in the Security class.
//ISecurity.php
abstract class ISecurity
{
public abstract function doEncode($encode);
protected abstract function doDecode($decode);
public abstract function doSuperGlobal($security);
protected $sencode;
protected $sdecode;
protected $sun;
protected $spw;
protected static $hookup;
protected $tablemaster;
protected $codedTable;
protected $unique=true;
//Register user or prompt to use different user name
protected function regOrRetry()
{
if(!$this->unique)
{
echo "This user name is already taken. Try a different one.";
}
else
{
$this->reg=new Register();
$this->reg->doRegistration($this->tableMaster,$this->sun,$this->spw);
}
}
}
?>
|
The abstract class sets up three abstract methods for flexible implementation, each with a single parameter. The protected properties provide sources for passing data between the several methods with different abstract class implementations. Finally, the regOrRetry() concrete method checks whether the user name is unique based on a Boolean ($unique) and either tells the user to try a different user name or passes the login information to the final object, Register.
The implementation, in this example, uses the built-in PHP encode and decode methods with the doEncode() and doDecode() methods, respectively. The goSuperGlobal() implementation, by contrast, is a bit more involved.
Superglobals (discussed elsewhere on this blog) are programming devils and angels. In general, computer scientists warn us not to use global variables because they can lead to unwanted surprises—a value may be changed somewhere in a global and wrongly influence another part of the program. To deal with globals and superglobals, the general course of action is to not to use globals and reference and encapsulate superglobals once. However, with superglobals, developers need to guard against injection attacks when first assigned to an encapsulated property. One way is to use mysqli::real_escape_string() as has been done in the Security implementation.
//Security.php
class Security extends ISecurity
{
public function doEncode($encode)
{
$this->sencode=base64_encode($encode);
return $this->sencode;
}
protected function doDecode($decode)
{
$this->sdecode=base64_decode($decode);
return $this->sdecode;
}
public function doSuperGlobal($security)
{
$this->codedTable=$security;
self::$hookup=UniversalConnect::doConnect();
$this->tableMaster=$this->doDecode($this->codedTable);
//Uses real_escape_string() with text input to make
//injection attacks difficult
$this->sun=self::$hookup->real_escape_string($_POST['username']);
$this->spw=self::$hookup->real_escape_string($_POST['password']);
$this->sql ="SELECT * FROM $this->tableMaster";
try
{
$result = self::$hookup->query($this->sql);
printf("Select returned %d rows.", $result->num_rows);
while ($row = $result->fetch_assoc())
{
if($row['un']==$this->sun)
$this->unique=false;
}
$result->close();
}
catch(Exception $e)
{
echo "Here's what went wrong: " . $e->getMessage();
}
self::$hookup->close();
$this->regOrRetry();
}
}
?>
|
Backing up, we can see that the entire process was really just three modules:
- UI
- Security
- Registration
The MySQL connection was handled by two helper classes (IConnectInfo and UniversalConnect.
The Login and Security Game
In Part II of this two-part series, I want to take a look at the flexibility of this design. The actual login form has been discussed elsewhere on this blog in seeing how to use a Proxy design pattern. We’ll take a look at that again and see how it can be integrated into the current system. Also, we need to look at how Registration and Login can be combined to make it easy for the user.
The “security game” is one played by two sides who take turns in defense and offense. Hackers peel back a security mechanism and write code to defeat it. In turn, security developers write code to defend against security breaches. As a result, no security system is safe for long. However, on the security side, we keep trying, but never assume that you have the “final security system.” Believing you do can spell disaster for you and your customers.
As always, I look forward to your comments and ideas.
Copyright © 2014 William Sanders. All Rights Reserved.
Great Blog! The download files on this article isn’t working. Can you please fix it?
2 questions –
1. You have mentioned in a few of your articles that using conditional loops is not advisable. Instead use object calls. Why is that so?
2. What is the recommended approach – using heredoc or creating another html file but with php extension and then using it in the include tag?
Hi Amitesh,
1. The main reason that I avoid conditional loops is that they can be very hard to update, re-use and debug.(They can tangle your code like a ball of twine!) With recursive functions, you have conditionals but not loops, even though they function like loops in repeating an operation. They are easier to untangle and debug. As for using objects instead of conditional loops; I was probably referring to having a set of conditions that are requested in the same PHP file. Avoid long and unwieldy conditionals that lead to functions and more functions in the same PHP file. Rather, favor composition, and use class-objects for different requests.
2. I recommend getting rid of all “free range chickens” in HTML code. That is, encapsulate your HTML (esp HTML5!) in PHP classes. Then, you can use all of the advantages of an OOP class with your HTML code, including implementations of interfaces and inheritance.
Kindest regards,
Bill
Thanks Amitesh,
Whoops! My bad…I had a typo in the file name. You can now download it.
Happy PHP OOP Computing,
Bill
Bill – THANK YOU SO MUCH to both of my questions, especially the conditional loops one. It makes perfect sense. Last question – I believe in having php files for all my code (including html) but include the html code in a separate file which is than called by my index.php file. However, in your code you used Heredoc. Is there any best practices around using my way vs. yours (as in using Heredoc is more secure etc.)?
Great Bill! The download works now.
I just got onto OOP PHP and loving every bit of it (never used an OOP language in my life) and your blog has been superb in this journey.
There are a couple of other places in the blog where the download isn’t working. When I have time later, I will send you those articles so you can fix the broken links.
Hi Amitesh,
Developers treat HTML in all different kinds of manner. Some just slap on “.php” to the end of an HTML file name, some drop in PHP code (variables or functions) where they need it and some treat HTML as a one-time-UI. In this particular post you can see how the encapsulated HTML in a class is able to implement the IUI interface. The value of the constant in that interface can now be used in the class of which HTML is a part. The constant, BLETCHLY is encoded, and so all you can see in the source code (Figure 1) is the encoded name; not the actual name of the table. By being part of a class, your HTML has all of advantages of an OOP class. You don’t have to encapsulate external CSS or JS files, but calling them from an encapsulated class allows them to be “encapsulated-in-use”. So, I agree that encapsulating HTML in a class (heredoc is the easiest way) is a best practice for OOP PHP.
Kindest regards,
Bill
This code is bad. If I don’t add password, error doesn’t show up.
Coder,
You are absolutely right! Thank you for pointing that out. The focus of this post is to see how to use OOP to create a registration form, and I did not include error handling. That needs to be done, and I’m working on it now. In fact, this may be a good opportunity to use a lambda function.
I’ll race you. If you get it done first, you win! If I do, I win. We both have to follow good OOP practices and use a lambda function (anonymous function.) As soon as you’re finish, put your post here in the comments, and I’ll do the same.
Kindest regards,
Bill