Why coding standards? In big projects, in any project, they’re essential: understandeable, much easier, solid code. Perfect, mandatory for a team. The objective is to have all decisions documented, choices and standards that I will stick on when developing. Important thing is not to follow these guidelines, but to follow a set of them, whichever. It can be PEAR as this guy. My coding standards are based on Zend Framework Coding Standard for PHP, but some are mine. The result follows.
scope (as a table of contents)
As of today, topics in this php coding standards include:
- php architecture,
- why a framework?,
- why codeigniter?,
- file structure,
- version,
- developing,
- file formatting,
- php tag,
- indentation,
- lines,
- naming convention,
- coding style,
- parenthesis,
- braces,
- strings,
- switch,
- other,
- example,
- documentation,
- file,
- class, and
- function, method.
php architecture
Following this architecture, I prefer the Codeigniter framework. Codeigniter, in its wonderful yet easy and concise help, defines MVC as:
- The Model represents your data structures. Typically your model classes will contain functions that help you retrieve, insert, and update information in your database.
- The View is the information that is being presented to a user. A View will normally be a web page, but in CodeIgniter, a view can also be a page fragment like a header or footer. It can also be an RSS page, or any other type of “page”.
- The Controller serves as an intermediary between the Model, the View, and any other resources needed to process the HTTP request and generate a web page.
why a framework?
Frameworks provide us programmers with tested, ready-to-use tools to develop flexible and almost error-free applications effectively. PHP frameworks can include authentication classes, database access, caching, even web templates in case you need them. They help in the sense you can focus on design and business, and not in implementation details. You don’t have to reinvent the wheel for very common development needs.
why codeigniter?
Why not? It is lighter, easier, more flexible than symphony, cakephp and zend, support databases as Oracle which Kohana and Yii lack.
file structure
the-domain.com/
app/
config/
controller/
view/
model/
library/
helper/
(...)
public/
css/
js/
img/
(...)
File name: low case a-z, underscore separation: emission_dataset.php. All files have .php extension (no .inc for security issues). For classes, the file has same name as the class contained in it, still low case.
For backoffice files, begin with underscore: _users.php.
version
It is controlled by subversion.
developing
While developing, I use these conventions in comments:
- :TBD: to be done.
- :BUG: and the number assigned by the bug tracker.
- :WRN: some warning, maybe the code could be unstable depending on some conditions.
file formatting
file
Files are ASCII text with Western, ISO-8859-1 character encoding.
lines
- Maximum line length: 80 to 120 chars.
- Line terminations follow the windows standard: CRLF (both chr 13 and 10).
php tags
<?php: full open tag, available in all php configuration and thus preferred over the short one (), which can cause problems.<?php= $val; ?>as inline tag (and even better,<?php echo $val; ?>).- Not using
?>at the end of a file to avoid possible injections.
indentation
- Always 2 spaces and not using tabs, to avoid problems in different text editors and users.
- Align when possible:
$aColors = array( array( #FFF, #FFF, #FFF ), array( #0FF, #F0F, #FF0 ), array( #00F, #F00, #0F0 ), array( #000, #000, #000 ) );or another example:
$sName = ""; $iMaxFileSizeKb = 128; $aTypeAllowed = array( "jpg", "gif", "png" );
naming convention
classes
Capital first letter, underscore between words. Class name must match controller's and file name (except first letter). That means that each class must go in a different file. Models add "_model" at the end, as Dataset_model. Use of acronyms is allowed but without caps: Document_pdf and Document_pdf_model. Even if a word is an acronym, it must not be written in all caps (HTML, for example, would become Html).
functions and methods
Begin with small caps, then words begin with caps. No underscore between words. If suitable, use "Get" or "Set" as beginning. Explain what they do: getErrorCode, calcEmissions, showPdf, loadDataset.
variables
Since PHP vars can be of any type, even change in the same script, I prefer using the hungarian notation for stating the type with the first lower letter, then same as functions. Always initialized before used: $aColors = array();, $bEndFile = false;. Exceptions:
- Short loops:
$i,$j. - Coordinates:
$x,$y,$z. - Database:
$sql,$query,$db,$rs.
I do not use global vars. When needed, either a regular var in config or a session one.
constants
All caps and underscore between words: MAX_FILES_ALLOWED.
coding style
parenthesis
I do know that language constructs as if are different than functions as str_replace. But both work the same way and return values, so I try to keep same style with these calls. Always put spaces when using parenthesis, it is much easier to read:
if( $sUserType === "admin" )
$iLastUser = count( $aUsers ) - 1;
$sLastUser = $aUsers[ $iLastUser ];
$oDataset->loadPdf( $fName, $iFileSize, $sUrl );
braces
I always use braces in their own line:
for( $i = 0; $i <= $iLastUser; $i ++ )
{
if( ! empty( $aUsers[ $i ] ) )
{
echo( "user: ", $aUsers[ $i ], "<br/>" );
}
}
strings
I prefer double quotes, but never rely on magic quotes. Single quotes are used inside.
$sql = "SELECT id FROM users WHERE name = 'Pau' ";
When using concatenation, the . operator is placed under the assignment. Concatenation and caps are used in queries as follow:
$sql = "SELECT field1, field2 "
. " FROM table "
. " WHERE field3 = 'somevalue' "
. " ORDER BY field1 " ;
switch
Use continue and break sparingly, as they are masked go to. Always use a default. The switch follows this model:
switch( $erCode )
{
case 1:
...
break;
case 2:
...
break;
default:
}
other
- Never use global vars. Use session vars instead.
- Use of
echo( 1, " .- ", $var );instead ofecho 1 . " .- " . $var;orprint. - Use of
ifinstead of the ternary operator? :. - The
returnclause never uses parents. And it helps debugging if there is a simple variable to return. Any calculations or function calls must be done earlier:function getTableValue( $sTable, $sField ) { $sql = 'SELECT ' . $sField . ' FROM ' . $sTable; $db->query( $sql ); $val = $db->row[ $sField ]; return $val; } - No use of magical numbers like
if( $i > 15 ). Use variables and document them. - One statement per line. If possible, avoid embedded assignments like
if( $file = fopen( $url ) ) - Space after commas, as when writing.
- Do not use
abortordie, or the evil @ operator. Use a error handler, like:function exception_handler( $exception ) { echo 'Uncaught exception: ', $exception->getMessage(), 'n'; } set_exception_handler( 'exception_handler' ); throw new Exception( 'Uncaught Exception' ); - Use of operators like
===,!==(value & type) instead of==,!=(just value, type is casted). - Do not rely on the default values like zero, null or false; always check
if( $bGeneratePdf === true ). - Do not call functions in checking the end of a loop; assign them before:
$iNumUsers = count( $aUsers ); for( $i = 0; $i < $iLastUser; $i++ )
example
bad code
function copy($url,$dirname){
@$file = fopen ($url, "rb");
if (!$file) {
echo '<font color=red>Failed to copy
$url!</font><br<';
return false;
}else {
$filename = basename($url);
$fc = fopen($dirname."$filename", "wb");
while (!feof ($file)) {
$line = fread ($file, 1028);
fwrite($fc,$line);
}
fclose($fc);
echo "<font color=blue>File $url saved to
PC!</font><br>";
return true;
}
}
my code
function copyFile( $sUrl, $sDirName )
{
$iBufferRead = 1024;
try
{
$fIni = fopen( $sUrl, "rb");
}
catch(Exception $e) //this does not handle fatal errors, though
{
print("Couldn't open file");
}
if( !$fIni )
{
echo '<p class="error">Failed to copy',
$sUrl, '</p>';
return false;
}
else
{
$sFileName = basename( $sUrl );
$fEnd = fopen( $sDirName . $sFileName, "wb" );
while( ! feof( $fIni ) )
{
$sLine = fread( $fIni, $iBufferRead );
fwrite( $fEnd, $sLine );
}
fclose( $fEnd );
fclose( $fIni );
echo '<p class="succeed">File',
$sUrl, 'saved to PC!</p>";
return true;
}
}
documentation
Documentation must be compatible with phpDocumentor.
file
Each file starts with...
<?php /** * some_file.php * * Explains what it is inside the file. * * @copyright 2009 geometrus all rights reserved * @license http://geometrus.com/license * @version $Id$ (cvs keyword) * @link (where the file is placed) * @author Fulgencio Sanmartin <f@geometrus.com> * @since File available since Release 1.5.0 * * Audit: * 23/01/2009 [fulgen] created * 25/01/2009 [other] added some functionality * 26/02/2009 [fulgen] solved bug #3341 */
class
Apart from previous tags (see file), each class adds and is preceded of...
* @package sample * @subpackage classes
function, method
Apart from previous tags (see file), each function or method adds and is preceded of...
* @param string $param1 name to declare * @param string $param2 value of the name * @return integer

The php coding standards by geometrus, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
















Although some of my coding styles are different from yours, it is good to see it from your perspective. Articles like this help to establish the standards our PHP coding community so especially needs.
Thanks for your comment, Peter. I agree, and as I mostly work with other people’s code (like mediawiki), I think it’s important as well to be able to adapt your code to other rules.
Do you have your coding styles published? It would be interesting to compare.
Cheers!