Create Good PHP Classes

October 28, 2007

The most important part of programming, whether for the web or for applications, is software design. Not interface design, but the design of how the code is used, what it does, and how it works. Well designed programs are an amazing thing, and good design helps the quality of your code as well. Unfortunately, many programmers don’t know how to design good software.

This seems especially common in software development for the internet, which is probably caused by the simpleness of HTML. It’s relatively easy to create HTML pages, and browsers are tolerant of bad markup so any Tom, Dick, or Harry can make a website. The result is that a lot of people with little training learn bad habits and with no one to give them good feedback, end up producing lower quality work than they are capable of.

Start at the Start

Regardless of what language you’re building your site with, you have to get the basics right for the site to be successful. It doesn’t matter if you’re using PHP, ASP, or just HTML, you have to get it right. In the case of PHP, you can go with either procedural scriptx to run everything, or you can choose to use an Object Oriented approach and use classes to run your application.

However, good class design is one of those things that doesn’t get talked about. How do you create PHP classes that are easy to use and help reduce the amount of repetitive code? The first step is figuring out what you need the class to do. For example, a MySQL interface class would need a few standard things, such as connecting to the database, querying the database, getting results from the database, and checking how many rows were returned or affected. Changing those actions to functions, we get some basic PHP code.

class mysql_db {
    /* Creates the object */
    function mysql_db() { }

    /* Connects to the server and selects the database */
    function connect() { }

    /* Query the database */
    function query() { }

    /* Get a result from the query */
    function fetch() { }

    /* Get the number of rows */
    function num_rows() { }
}

And Then Take it Away

After that step, take a look at what actions you have, and determine what data you’ll need to be working with. In this case, the connect function will need a server, a username, a password, and a database. The query function will need an SQL statement, and the fetch and num_rows functions will need the return value of mysql_query function. We can take each of these items, and add them as class variables. That would look like this:

var $server;
var $username;
var $password;
var $database;
var $sql;
var $result;

Now would be the time to add parameters to the functions, but the only function that really needs parameters is the connect() function. All the other functions can use the class variables to get and store their data. Also, the constructor function could take the same parameters as the connect() function, to save a little bit of overhead when using the class.

When working with any kind of programming project, you want to make it as easy as possible to use, so when filling out the functions, keep in mind that simple code means that it’s faster and easier to write. In the normal use situation, you want to pass an SQL statement to the query() function, and then use the fetch() function to get results. If we assigned the result of the query to the class variable, we don’t need to pass any parameters to the fetch() function. Ideally, the query and fetch functions would look like this:

function query($sql) {
    $this->sql = $sql;
    $this->result = mysql_query($this->sql);
    return $this->result;
}

function fetch() {
    $row = mysql_fetch_array($this->result);
    if(is_array($row)) {
        foreach($row as $key => $value) {
            $row[$key] = stripslashes($value);
        }
    }

    return $row;
}

A few things to notice with this implementation is that the query function assigns the class $result variable, and that it also returns the variable. This is because it allows the query function to be used in other situations. Also, the fetch function automatically strips slashes from the row array. That allows for less post processing of the rows in the query result.

My Name is…

When naming functions, keep in mind that simple is best. Single words are ideal, but if that’s not possible try to keep the word count to a minimum. Descriptive functions names are essential.

It’s also very handy to be able to do a number of related actions with one function call, so if you keep writing the same thing over and over, make it into a function. In some cases, a class isn’t the proper solution to a problem. Sometimes, you just might need to create an include file with a bunch of useful functions. That’s up to you to decide.

It’s important to note that you shouldn’t make classes depend on other classes. Classes should be totally independent and able to function by themselves. The only exception to that is when two classes have an obvious parent-child relationship, and the child uses the extends keyword to establish that relationship.

Easter Egg

There’s an easter egg in this post. Can you find it?