On The Legibility of PHP

This is a very old article. It has been imported from older blogging software, and the formatting, images, etc may have been lost. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.

David Segall wrote:

I do not deny that the programmer is the most significant factor in the readability of a program but would you really promote PHP as a language because it is easy to read?

I certainly wouldn’t advise against it because of legibility concerns.

Any language that supports comments (not all do) and allows the programmer to choose variable and function identifiers using arbitrary alphanumeric names (again, not all do) can be made very readable simply by using these facilities. With most common programming languages, you can easily clarify your code by having a policy that includes choosing sensible, readable function and variable names, using indentation and plenty of white space, adding liberal comments, keeping line lengths down to a reasonable length, keeping function sizes down to 20 or so lines (longer functions can often be split into two or more functions). Yes, even Perl!

For example, consider the following two (untested) PHP objects which are exactly equivalent except identifier names, comments and formatting.

id = $customer;
$this->dirty = FALSE;

$this->data[‘name’] = $row[‘name’];
$this->data[‘address’] = $row[‘address’];
$this->data[‘postcode’] = $row[‘postcode’];
} // end if ($customer != ‘NEW’ && is_integer($customer))

// Check to see if we’ve actually (by now) managed to read
// an existing customer. If we haven’t then this is a new
// customer, so data cannot already be in database. Thus
// data is by definition “dirty”.
if ($this->id == -1)
$this->dirty = TRUE;

return $this;

/* [boolean] = save ([void])
* Saves data into the database. Takes no parameters,
* returns TRUE iff successful.
function save ()
// Firstly check to make sure we actually have anything
// worth saving. If not, then bail out and pretend that
// we actually saved the data by returning TRUE.
if (!$this->dirty)
return TRUE;

// We will certainly need this then!
global $db_connection;

// Which data do we want to save?
$save_data = array(
‘name’ => $this->data[‘name’],
‘address’ => $this->data[‘address’],
‘postcode’ => $this->data[‘postcode’]

// If the customer is new (customer ID will be -1)
if ($this->id == -1)
// We’ll need to insert into the database.
// The customer ID will be filled in by the DB engine.
$result = pg_insert($db_connection, ‘customers’, $save_data);

// Otherwise the customer must be an existing one
// Update database with new data.
$result = pg_update($db_connection, ‘customers’, $save_data,

// Return success
return $result;

/* [mixed] = attribute ([string] attribute, [mixed, optional] value)
* Gets or sets the attribute named in the first parameter.
* If a second parameter is provided, will set the attribute to
* that value. Will always return the value of the attribute.
function attribute ($attribute, $value=NULL)
// If the value is not NULL, then set the attribute
if ($value===NULL)
$this->data[$attribute] = $value; // change attribute
$this->dirty = TRUE; // and mark object as dirty

// Always return the value
return $this->data[$attribute];


and now the unreadable version:

id = $cid;
$this->dirty = 0;
$this->data[‘name’]= $X[1];
$this->data[‘postcode’] = $X[3];
if ($this->id == -1) $this->dirty = TRUE;
return $this;
function save_customer_2_database(){
if(!$this->dirty){return 1;}
global $DB;
$myarray= array(‘name’ => $this->data[‘name’],
‘address’ => $this->data[‘address’],
‘postcode’ => $this->data[‘postcode’]);
if ($this->id == -1)
return pg_insert($DB, ‘customers’, $myarray);
return pg_update($DB, ‘customers’, $myarray, array(‘id’=>$this->id));
function GetAttribute ($a, $v=NULL) {
if ($v===NULL)
$this->data[$a] = $v;
$this->dirty =1;}
return $this->data[$a];

What a difference!