How to Refactor a PHP Application

Matt McCormick

2011/10/13

The great thing about PHP is how easy it is to get started.

The bad thing about PHP is how easy it is to get started.

I’ve worked on a few PHP sites where the code lived up to these statements. While it is incredibly easy to get a site up and running with PHP, that ease of getting started could turn into a nightmare as the site grows and becomes more complex.

When you’re faced with a site which has no separation of view code, business logic and model code, it can be daunting to figure out where to start. Here is a simple list you can follow to keep from getting overwhelmed.

1. Write PHPUnit Tests

In Martin Fowler’s book on Refactoring, he proposes to always write tests before changing code. It is an easy way to know that the output remains the same even if the underlying code has changed. I think this is a great practice to follow, however, with a PHP site that may not necessarily be broken into neat, testable units, this may be a difficult process to follow.

Edit: Since I posted this, I came across the SimpleTest testing framework which provides an excellent format for testing PHP applications by imitating the browser.

2. Create models

If you have MySQL queries mixed in with HTML code, the first thing I like to do is get that SQL outta there! SQL should only be seen inside model classes. Each mysql_query() function should be replaced with a call to a model’s method for the table that is being accessed. For example, if there is a statement like:

mysql_query("SELECT * FROM users WHERE id = $id");

I would create a Users.php class that can be used as a model for the users table. Since the code above is needed quite often, it would be a good idea to have a parent class that the Users class can extend from which implements something like a find_by_id() method.

That would allow you to something like:

$users = new Users(); $user = $users->find_by_id($id);

If the site isn’t using PDO, this is also a good time to set that up. There is no reason not to be using PDO these days. It helps with security and Object-Oriented design while keeping queries cleaner.

3. Consolidate duplicate code

I’m a big fan of DRY - Don’t Repeat Yourself - and have worked many times with sites that have a lot of duplicated code. After separating the models, identify duplicated code and start separating that code into libraries. Use a tool like PHP Copy/Paste Detector which can help identify duplicate code or just keep your eyes open for code that looks like you’ve come across it before.

4. Separate views and controllers

Once the model code is separated out, the view and controller code should be separated from each other. In combination with the previous step, sometimes the header or footer HTML might be duplicated throughout the site. It’s good to create a standard layout that contains the common HTML. You might choose to use a templating tool like Smarty which can help to make sure PHP code stays outside of your templates and views.

5. Clean up PHP errors and notices

Make sure you have PHP error_reporting turned on to include all errors including Strict. (In PHP 5.4, E_STRICT will start to be included under E_ALL). This can help you identify stray variables, deprecated code, non-existent array indexes and much more. Cleaning up these errors and notices will make your application run smoother and can help reduce bugs.

Refactoring a whole PHP application can seem like a daunting task. Depending on the size of the application, it’s not something that can be done overnight or even within several weeks. It may take several months of minor, gradual improvements but the end result will be worth it. You’ll be able to add new features quicker, reduce the number of bugs and increase your enjoyment while working on the application.

These steps may not all be applicable to your refactoring challenge but the key thing to keep in mind is to break down a large and complex refactoring job into a series of smaller parts and steps.