Like many developers my age, I was predominantly self-taught. I went to art school to learn how to make things pretty, and I learned the code I needed mostly on my own. For quite some time, I had been given the impression that how you code PHP is irrelevant. As long as the code works, its just as valid as any other code that runs without critical error. But lately I’ve been digging a little deeper in to that well and have since realized that there is in fact a scale and a standard for syntax-related best practices.
Coding Standards
Every programmer has personal preferences as far as indenting, code tags, and naming conventions. The idea of being able to impose a strict set of parameters on style is ridiculous. But I do believe that every programmer has a responsibility to account for their decisions rather than leaning on the “it’s just how I’ve always seen it done” standby. I personally prefer the PEAR coding standards because they ensure legibility, accuracy, and consistency. Here are just a few examples and preferences of mine:
- PHP Code tags. Always use <?php and ?> instead of the <? and ?> shorthand. Not only will this make your code more portable, but it just makes more sense. Many programmers still insist that you don’t need a closing PHP tag at the end of your file, but as a throughback to my XHTML roots, I can’t stand to open a tag and not close it again. I have yet to find functionality specifications for why this is a good or bad idea, but my preference is that everything be balanced.
- Naming Conventions. Generally this is a pretty flexible area, but I am a strong advocate of consistency here and I am partial to the PEAR methods: class variables and methods in camel case, classes use underscores, globals in all-caps.
- Return functions early. If your function has simple parameters that can be validated at the beginning of the function, don’t make PHP process the rest of the logic before returning a false value. Consider the following construct:
<?php function foo($bar, $baz) { if ($foo) { //here is the //whole logic of //this method return $calculated_value; } else { return null; } } ?> - Use tabs for readability. Aside from indenting your code, use tabs within function calls, loops, or arrays to aid in readability. Consider the following two examples and decide which looks better:
//life worth living $this->someFunc('param1', 'second', true); $this->someFunc('parameter2', 'third', false); $this->someFunc('3', 'verrrrrrylong', true); //soul-crushing disappointment $this->someFunc('param1', 'second', true); $this->someFunc('parameter2', 'third', false); $this->someFunc('3', 'verrrrrrylong', true);
Coding for Efficiency
One of my biggest beefs with PHP tutorials I’ve seen throughout the Web is that they very rarely account for the efficiency or logical construction of code. Here are just a few examples of things that I didn’t know until just a few months ago (and I’ve been writing PHP for over 5 years):
- Double quotes or single quotes. There is actually a very large difference between these two statements:
<?php
echo "I will do something with $variable";
echo 'I will do something with ' . $variable;
?>
Using double-quotes with an echo or print statement is indicating that PHP should scan the entire string for the presence of variables. I’ve seen many programmers who, out of habit, use this method as opposed to concatenation. However, if you consider the size of the string and additional processing required to scan the entire thing for variables, rather than using single-quotes and basic concatenation, you can see how one would be substantially more efficient than the other. I also prefer the concatenation method because it’s easier to pick out the variables from the crowd (if you use a color-coding editor that is).
- Pre- or post-increment. Similar to the single and double quotes, there is also a difference between ++$x and $x++. According to Zend, pre-incrementation is a much faster process than post-incrementation. The same principle applies to decrementation.
- require() or include(). Simply put, the require() function loads a file regardless of whether your script actually uses it or not. The include() function only loads a file when it is needed. For this reason, I generally avoid using the require() function at all, and I prefer to use the include_once() function for simplicity.
- Eliminate in-line or redundant function calls in loops. Loops are one of the worst enemies of efficiency. For example, a common issue like incrementing through elements of an array, can be easily overlooked as an efficiency issue. Your first instinct might be to structure this by using the count($myArray) function in your conditional statement. However, if the value of count($myArray) remains constant and is not impacted by the loop, why call that function every single iteration? Consider structuring it like this:
$arraySize = count($myArray);
for ( $i=0; $i<$arraySize; ++$i ) {
// do something
}
Other things to watch out for in loops or switches include creating/destroying objects inside of a loop and excessive function calls. Another little tidbit…when using a switch-case statement, put the most frequently-occurring cases at the top. That way, PHP won't have to read as much code before it finds the right choice.
Readable Code
A combination of consistent coding standards and efficient development practices can help ensure your code is both readable and maintainable. Anyone who has ever had to pick through a script written by someone who could care less about these things can attest to that. But I also believe that it is the programmer's responsibility to accurately document their code. Automatic documentation generators like phpDocumentor are quite popular right now, but I still prefer to do it by hand as I feel it makes me more accountable for my work. My general rule is, if it doesn't add value to the code than it doesn't belong there. Here are my recommendations:
- Headers. Don't get me wrong, I don't advocate the massive 50-line header comments I've seen in many a script in the past, but I do think it is important to document the intention or classification of a script, the author, last-modified date, and development intentions. Here is an example of one of my headers.
/*
Project: CMS v2.0
Description: User Authentication Class
Author: Lauren Haman, 11/04/2009
Last Updated: 12/21/2009
Development Goals: Add access control functions (2/2010)
*/
I generally don't advocate including excessively long file descriptions here. Some coders add lists of all required includes; I choose to solve that issue by keeping all my includes near the top. I've seen other coders include extensive inventories of function descriptions; I prefer to handle that type of documentation in-line. I like to rely on a reasonable level of intuition when dealing with headers. Most programmers already have a basic idea of what might go in a user authentication class, for example. This particular aspect is personal preference, but I've generally found it easier to read code that is concise, to the point, and not burdened by excessive copyright attempts (come on guys, it's open source, if you don't want your code "borrowed" then don't put it on the web).
- Function Documentation. Similar to the file headers, I also try to document my function and class declarations with a simple header indicating it's purpose, expected input, and output.
/*
Function: fooFunction, returns the product of two numbers
Input: $arg1 and $arg2 integers
Output: integer
*/
function fooFunction($arg1, $arg2) {
}
I've often found this helpful during the planning stages of my code. Being able to start a file by outlining all the functions I need to write, what they do, and what they will output is helpful in terms of project planning and timing, particularly if outsourcing is required.
- In-line Documentation. For me, this is the trickiest. I like to include enough in-line documentation to reflect my intentions without becoming a burden. I generally limit in-line documentation to complex portions of code where the logic isn't necessarily intuitive or easy to understand. However, this one is more fluid than other forms of documentation. You can use as much or as little as your code requires.
Additional Resources
Did I Miss Anything?
My work is constantly evolving, and if you think I've missed something important or disagree with me about a particular point, feel free to join the discussion.