PHP lets developers write ugly code. And I mean really ugly, unmaintainable, horrific code. I’ve had to work on my share of projects that would make spaghetti code look organized. It doesn’t have to be that way though. Seasoned developers know the benefit of organized code. One organization technique that I believe is essential is the practice of separating display code from logic code. Lets discuss a couple methods of handling this in PHP.
A simple method
One of the simplest methods you can employ is just separating code that generates HTML from the rest of your code. Using the PHP project structure I described previously, all the HTML generation code would reside in the www directory, and everything else would exist in classes in the lib directory.
By “HTML generation” code, I mean any code whose sole purpose is to format and display HTML. This would include all echo and print statements, as well as loops to iterate over data sets. Any business logic or data access code would be considered “logic” in this case, and should be separated from the display.
Why is this a good practice? Lets look at two examples.
Example #1 with no separation of display and logic:
<?php
$sql = "SELECT * FROM users WHERE username = 'luke'";
$stmt = $pdo->prepare($sql);
$row = $stmt->fetch();
echo "Hello {$row->first_name} {$row->last_name}!";
?>
Example #2 separated into a User class, and a display script:
<?php
class User {
...
public static function get_user($username) {
$sql = "SELECT * FROM users WHERE username = :u";
$stmt = $pdo->prepare($sql);
$row = $stmt->fetch();
return new User($row);
}
...
}
?>
<?php
include_once("classes/User.inc");
$user = User::get_user("luke");
echo "Hello {$user->first_name} {$user->last_name}!";
?>
While Example 2 is certainly a bit more code up front, can you see the benefit over Example 1? There is now a reusable method called User::get_user() that can be used everywhere. This also allows for unit testing of the User class, to ensure that the method always works as we would expect; division of labor, to allow some programmers to work on back-end classes while others focus on the front-end display; and it is more maintainable, since we only have one place that fetches a user from the database instead of duplicating that logic all over our site.
The model, view, controller (MVC) method
Another popular code organization method is called MVC for model, view, controller. This has been popularized in recent years by the rise of Ruby on Rails which uses the MVC method by default. For larger projects, this is an excellent way to organize code. In the interest of time, I won’t delve into examples. In general though, here is how each part of MVC is differentiated:
Model - The model can be thought of as a data container. It would be a User or a Product class that holds all the information about something. This would also include the database which is where the data actually resides. View - The view is usually some sort of template that takes models and creates a meaningful interface with which the user interacts. This would be very similar to the “display” part of the previous example. Controller - The controller can be thought of as a traffic cop. This part is in charge of instantiating models and passing them to views. The controller glues everything together and delegates user actions to the right places.
This can be done in PHP easy enough by differentiating your classes into models and controllers, while still keeping your view clean of any business logic. A true MVC model would likely use a template engine instead of echoing HTML directly from a PHP script, and the PHP script would act as part of the controller.
Conclusion
You should use whatever method works best for any given situation. No one solution is the best. However, you should always use some sort of organization technique, or your code will end up being a nightmare to maintain. Remember: "Always code as if the person who will maintain your code is a maniac serial killer who knows where you live."