Yes, I admit it. Despite the curious title, this is actually an article about coding styles, naming conventions, and where those little curly braces should be going. But take a second to consider the prospect of returning to a PHP jungle of poor indentation, haphazard braces and cryptic variable/function names in 2 year old code... and you might consider reading further!
Personal or Prescriptive?
As long as you're consistent, why shouldn't you use your own unique style? Well, none of us code in a complete vacuum - your code needs to be maintained by your current and future colleagues, and most projects entail at least some collaboration. A funky mix of two different coding styles is almost as bad as no coding style at all.
Conventions are your friend, be boring and use them. Seriously, they have generally developed over time as the most popular methodology. When referring to coding style, the popular way is what most people find easiest to understand. Use that.
- Good Points
- Anybody can look at your code and figure out what's gong on.
- People make fewer mistakes in consistent environments.
- Bad Points
- The standard is usually stupid because it's not what I do.
- Standards stifle creativity.
Capitals, Underscores and Naming
Names are at the core of any programming language, labelling variables, functions, classes and so on. In their creation, the single most important consideration is making names that fit. Never use nonsense names. Use a name that will intuitively give the unfamilar reader at least a clue what it is used for. Nonsense names are often used in academic computer science tests as generics, but even here such names serve no useful purpose and add nothing to the reader's understanding of the code.
The exception to this rule are temporary variables. Because these variables usually exist only within a small block of code, they do not need to have explanatory names. They should be short and concise. In particular, numeric variables used for iteration should always be named i, j, k, m or n. Try to avoid the use of l, it looks too much like the number one!
Name wisely, it makes a huge different to code readability:
PHP 5
<?php// BAD naming.. what's going on here?function test($baz){for ($foo=0;$foo<$baz;$foo++) {$bar[$foo]="test_$foo";}return $bar;}// GOOD naming.. intuitive.function createTestArray($size){for ($i=0;$i<$size;$i++) {$retval[$i]="test_$i";}return $retval;}?>
In addition to descriptive names, capitalisation and underscore conventions can help us to recognise what something is (i.e. variable, function, etc.) simply by the format in which it is named. The PEAR coding standards are the usual conventions for PHP: its rules are summarised in the table.
| Type | Convention | Example |
|---|---|---|
Note that abbreviations should not be capitalised in names just because they are abbreviations. The function name printXhtml() is correct, printXHTML() is not! |
||
| Variable | all lowercase, use _ as a word separator | $my_variable |
| Constants | all uppercase, use _ as a word separator | $MY_CONSTANT |
| Functions | capitalise first letter of each word apart from the first (Camel caps) | myFunction() |
| Classes | capitalise first letter of each word (Pascal case) | MyClass |
| Class Methods | capitalise first letter of each word apart from the first (Camel caps) | myMethod() |
In PHP 4, private class properties and methods are conventionally prefixed with an underscore. This is useful to indicate your intentions to another developer, but unnecessary if you are coding in PHP 5 as you can explicitally declare the visibility.
Namespaces
Lets illustrate the issue with an example: two PHP libraries need to be combined - one deals with xml operations and has the class File. One caches web-pages and also has a File class. The problem is obvious: the two names clash and both libaries can't both be used in the same script.
One solution often used in other languages is Namespaces. These are abstract containers that can be
used to prevent name clashes with different libraries. For instance, in the original example we might define a namespace for each library, and then be able to use both File classes in one script, using the namespace label to differentiate between them. Unfortunately, namespaces didn't quite make it into PHP5, but at least they are likely to be included in PHP6.
In the meantime, without namespaces, what's the solution? Many developers simulate namespaces by adding prefixes to function and class names. In fact, this practice is recommended by the core PHP team. Such prefixes should be short and concise, and separated from the function or class name by an underscore.
In our example, we might have chosen XML as the namespace prefix for one library, and WEBCACHE as the prefix for the other. If we have followed these prefixing rules, our two classes would be named XML_File and WEBCACHE_File. Simulating namespaces isn't pretty, but it is does solve the problem. If necessary it's also possible to nest these simulated namespaces by adding more than one prefix also separated by an underscore.
Indenting, Line Length and Whitespace
In addition to naming conventions, code clarity can be greatly aided by a neat consistent layout. For example, the importance of indentation for organising your code cannot be exaggerated. Indentation is such an in-grained aspect in any programmer there is little need to stress its value. However, the nature of the indentation is often overlooked: there are several types of tabs and these will render differently across various IDEs. The choice lies between regular tabs and "soft" tabs. Soft tabs are not really tabs at all: each soft tab is actually represented by a certain number of spaces (usually four). I would recommend the use of soft tabs as they always appear the same, regardless of the editor's tab-spacing settings.
Most editors support soft-tabbing, and many editors auto-detect such formatting conventions based on "magic" comments in the source code. For example, the following comment sets the editor to use 4-space soft tabs in vim or emacs:
PHP 5
<?php/** vim: expandtab softtabstop=4 tabstop=4 shiftwidth=4** Local variables:* tab-width: 4* c-basic-offset: 4* indent-tabs-mode: nil* End:*/?>
Keep lines short: I break up any line that is over 80 characters long (the width of a standard Unix terminal window, and a reasonable width for printing without wrapping). In addition, don't hesitate to use extra whitespace to group assignments and show associations. Compare the two identical examples below that differ only in terms of whitespace:
PHP 5
<?php// example of POOR use of whitespace:$host='db.example.com';$username='phpuser';$passwd='mypwd';$db_name='mydb';$dbh = mysql_connect($host,$username,$passwd)or die('db failure.');mysql_select_db($db_name,$dbh) or die('db name failure.');$query = 'SELECT Name FROM country LEFTJOIN CountryLanguage ONCode=CountryCode WHERE CountryCode IS NULL';$result = mysql_query($query,$dbh);// reformatted to make BETTER use of whitespace:$host = 'db.example.com';$username = 'phpuser';$passwd = 'mypwd';$db_name = 'mydb';$dbh = mysql_connect($host,$username,$passwd)or die('db failure.');mysql_select_db($db_name,$dbh)or die('db name failure.');$query = 'SELECT NameFROM country LEFT JOIN CountryLanguageON Code=CountryCodeWHERE CountryCode IS NULL';$result = mysql_query($query,$dbh);?>
Braces
There are two bracing conventions often used in PHP code: K&R and BSD styling.
PHP 5
<?php// K&R Braces:if ($condition) {// statement}// BSD Braces:if ($condition){// statement}?>
For some, bracing styles is a passionately debated topic. I don't really see what all the fuss is about, myself, but you do need to be consistent. I follow the PEAR convention of using the more concise K&R styling for control structures, and the longer BSD styling for function and class declarations.
PHP 5
<?phpfunction isEven($number){if ($number & 1) {return false;} else {return true;}}?>
Code Comments
Documenting your code is very important, and although it will not be discussed any further here, I strongly recommend the phpdocumenter package. It's an invaluable tool, and brings the added advantage of a set of conventions with which to comment your code.
Non-documentation comments (or "inline comments") are also essential, to help understand what your code is actually doing rather than to describe the API to a potential user. Use C or C++ style comments (forward-slash star, or double forward-slash prefix) rather than the Perl-style comments (a hash prefix). Remember that inline comments should be used to clarify code - a classic example of a worthless comment is:
PHP 5
<?php// increment i$i++;?>
This comment doesn't add anything - it simply reiterates what should be obvious by reading the code. Your comments should aid understanding rather than just clutter the code:
PHP 5
<?phpfunction isEven($number){// use the bitwise AND operator to see if// the first bit in $number is set, to// determine if it is odd/even.return !($number & 1);}?>
Out, Out, You Pendant!
We've now covered the cornerstones of good code style: naming, indentation, braces and commenting. There's plenty of other useful conventions, but this article is not the place for a comprehensive list of them all. Instead, I will leave you with a few that I regard the most useful:
- Always use full php tags:
PHP 5
<?php ... ?>
- Avoid using
echoto construct XHTML. One of the beauties of PHP is that it allows for embedding of PHP in XHTML. You should take advantage of this ability. - Add a single space after control construct keywords (
if, while, foreach, ...) to differentiate them from function calls. For example:PHP 5
<?php$my_variable = myFunction($arg1, $arg2);if ($condition) {// statement}?>
That's it! No more code spagetti from now on, you promise?