• php logo
  • smarty logo
  • adodb logo
  • SourceForge.net Logo
  • zend framework logo

Tangra PHP5 Code Conventions

1.Intro

Code conventions contain rules and recommendations about visual formating of the code. They are important for the humans, not for the computers.

Code conventions are important to programmers for a number of reasons:

2.File names

2.1.File suffixes

2.2.Common Files

3.File organization

Files longer than 500 lines should be avoided.

A file consists of sections that should be separated by blank lines and an optional comment identifying each section. Section separation is recommended to be done with 2 blank lines.

3.1.Beginning comments section

All files should begin with single line comment containing product name – this helps to detect problems in code that is mistakenly grabbed from another project.

Optionally may have $Id expandable CVS/SVN tag.

Other lines may be specified by conventions of given product.

3.2.Require and include statements section

Always use require_once() statement. Using require() is deprecated.

Include() statements also have to be avoided (they don't make sense in pure php context).

Put first require_once() statements that include general libraries and after them require_once() that include application/site specific files (this is common sense – application specific files is natural to depend on libraries).

It is strongly recommended to keep all of your require_once() statement at top of the file, just after the beginning comments. Failing to comply with that may lead to confusion and unrepeatable bugs that are hard to find. Usage of “inner” require_once is acceptable only in “low” level code as libraries or startup (boot) scripts that are normally not visible to end user (developer).

Conditional require_once should be avoided at all – that is a sign of bad design.

“Autoloading” (automatic loading via __autoload function or another method) may sound as good idea, but it also makes code harder to read and comprehend.

Both conditional includes and autoloading are generally bad idea because of lack of namespaces in PHP – it is easy global variables to be overwrited in some autoloaded code.

3.3.Code section

Code section can contain class/interface definition OR either global function definitions OR global code.

3.3.1.Class definition

3.3.1.1.Optional class comment

Comment describing class purpose, used algorithms, assumptions, etc.

3.3.1.2.Class/interface statement
3.3.1.3.Static variables
3.3.1.4.Instance variables

First public, then protected, then private.

3.3.1.5.Constructor
3.3.1.6.Methods

It is good idea to put first public methods, with the following exception: methods should be grouped by functionality rather than by scope or accessibility. For example, a private class method can be in between two public instance methods. The goal is to make reading and understanding the code easier.

Methods have to be separated by two blank lines.

3.3.2.Global functions

Each function can be preceded by optional comment.

Functions have to be separated by two blank lines.

3.3.3.Global code

Each code that is contained in a file outside of methods and functions should be considered global (because of the rules for require() statements.

Global code is allowed only in startup/boot scripts.

4.Indentation

Tab with size 4 spaces must be used for indentation.

4.1.Lines length

Avoid lines longer than 100 characters, since they're not handled well by many terminals and tools.

Note: Examples for use in documentation should have a shorter line length-generally no more than 90 characters.

4.2.Wrapping lines

When an expression will not fit on a single line, break it according to these general principles:

Here are some examples of breaking method calls:

some_method($long_expression1, $long_expression2, $long_expression3, 
        $long_expression4, $long_expression5);
 
$var = some_method($long_expression1,
                some_method2($long_expression2,
                $long_expression3)); 

Following are two examples of breaking an arithmetic expression. The first is preferred, since the break occurs outside the parenthesized expression, which is at a higher level.

$long_name1 = $long_name2 * ($long_name3 + $long_name4 - $long_name5)
           + 4 * $long_name6; // PREFER

$long_name1 = $long_name2 * ($long_name3 + $long_name4
                       - $long_name5) + 4 * $long_name6; // AVOID 



Following are two examples of indenting method declarations. The first is the conventional case. The second would shift the second and third lines to the far right if it used conventional indentation, so instead it indents only 2 tabs.

//CONVENTIONAL INDENTATION
public function some_method($an_arg, Object $another_arg, $yet_another_arg, Object $and_still_another) {
    ...
}

//INDENT 2 TABS TO AVOID VERY DEEP INDENTS
private static horking_long_method_nName($an_arg,
        Object another_arg, $yet_another_arg,
        Object and_still_another) {
    ...
}



Line wrapping for if statements should generally use the 2-tabs rule, since conventional (1 tab) indentation makes seeing the body difficult. For example:

//DON'T USE THIS INDENTATION
if (($condition1 && $condition2)
    || ($condition3 && $condition4)
    ||!($condition5 && $condition6)) { //BAD WRAPS
    do_something_about_it();           //MAKE THIS LINE EASY TO MISS
} 

//USE THIS INDENTATION INSTEAD
if (($condition1 && $condition2)
        || ($condition3 && $condition4)
        ||!($condition5 && $condition6)) {
    do_something_about_it();
} 

//OR USE THIS
if (($condition1 && $condition2) || ($condition3 && $condition4)
        ||!($condition5 && $condition6)) {
    do_somethings_about_it();
} 



Here are three acceptable ways to format ternary expressions:

$alpha = (aLongBooleanExpression) ? $beta : $gamma;  

$alpha = (aLongBooleanExpression) ? $beta
                                 : $gamma;  

$alpha = (aLongBooleanExpression)
        ? $beta 
        : $gamma;  

5.Comments

PHP code can have two kinds of comments: implementation comments and documentation comments. Implementation comments are those found in C++, which are delimited by /*...*/, and //. Documentation comments (known as "doc comments") are delimited by /**...*/. Doc comments can be extracted to HTML files using the phpdoc tool.

Implementation comments are mean for commenting out code or for comments about the particular implementation. Doc comments are meant to describe the specification of the code, from an implementation-free perspective. to be read by developers who might not necessarily have the source code at hand.

Comments should be used to give overviews of code and provide additional information that is not readily available in the code itself. Comments should contain only information that is relevant to reading and understanding the program. For example, information about how the corresponding package is built or in what directory it resides should not be included as a comment.

Discussion of nontrivial or non obvious design decisions is appropriate, but avoid duplicating information that is present in (and clear from) the code. It is too easy for redundant comments to get out of date. In general, avoid any comments that are likely to get out of date as the code evolves.

Note:The frequency of comments sometimes reflects poor quality of code. When you feel compelled to add a comment, consider rewriting the code to make it clearer.

Comments should not be enclosed in large boxes drawn with asterisks or other characters.
Comments should never include special characters such as form-feed and backspace.

5.1.Implementation Comment Format

Programs can have four styles of implementation comments: block, single-line, trailing, and end-of-line.

5.1.1.Block Comments

Block comments are used to provide descriptions of files, methods, data structures and algorithms. Block comments may be used at the beginning of each file and before each method. They can also be used in other places, such as within methods. Block comments inside a function or method should be indented to the same level as the code they describe.

A block comment should be preceded by a blank line to set it apart from the rest of the code.

/*
 * Here is a block comment.
 */

5.1.2.Single-Line Comments

Short comments can appear on a single line indented to the level of the code that follows. If a comment can't be written in a single line, it should follow the block comment format. A single-line comment should be preceded by a blank line. Here's an example of a single-line comment in PHP code:

if ($condition) {
    /* Handle the condition. */
    ...
}

5.1.3.Trailing Comments

Very short comments can appear on the same line as the code they describe, but should be shifted far enough to separate them from the statements. If more than one short comment appears in a chunk of code, they should all be indented to the same tab setting.

Here's an example of a trailing comment in Java code:

if ($a == 2) {
    return TRUE;            /* special case */
} else {
    return is_prime($a);      /* works only for odd a */
}

5.1.4.End-Of-Line Comments

The // comment delimiter can comment out a complete line or only a partial line. It shouldn't be used on consecutive multiple lines for text comments; however, it can be used in consecutive multiple lines for commenting out sections of code. Examples of all three styles follow:

if ($foo > 1) {

    // Do a double-flip.
    ...
}
else {
    return false;          // Explain why here.
}
//if ($bar > 1) {
//
//    // Do a triple-flip.
//    ...
//}
//else {
//    return false;
//}

6.Declarations

PHP itself doesn't require explicit declaration of normal (non class members) variables.

6.1.Number Per Line

One declaration per line is recommended since it encourages commenting. In other words,

private $level; // indentation level
private $size;  // size of table

is preferred over

private $level, $size;

Note: The examples above use one space between the type and the identifier. Another acceptable alternative is to use tabs, e.g.:

private	$level;          // indentation level
private	$size;            // size of table
protected	$current_entry;    // currently selected table entry

6.2.Initialization

Always initialize new variables with meaningful values.

	$c = 0;
	while ($c < $a) {
	    // do something...
	    $c++;
	}



$length = strlen($a);

6.3.Class and Interface Declarations

When coding PHP classes and interfaces, the following formatting rules should be followed:

class Sample extends Object {
    public $ivar1;
    public $ivar2;

    public function Sample($i, $j) {
        $this->ivar1 = $i;
        $this->ivar2 = $j;
    }


    public function empty_method() {}

    ...
}

7.Statements

7.1.Simple Statements

Each line should contain at most one statement. Example:

$argv++;       // Correct
$argc--;       // Correct  
$argv++; $argc--;       // AVOID!

7.2.Compound Statements

Compound statements are statements that contain lists of statements enclosed in braces "{ statements }". See the following sections for examples.

7.3.return Statements

A return statement with a value should not use parentheses unless they make the return value more obvious in some way. Example:

return;

return $my_disk->size();

return ($size ? $size : $default_size);

7.4.if, if-else, if else-if else Statements

The if-else class of statements should have the following form:

if (condition) {
    statements;
}

if (condition) {
    statements;
} else {
    statements;
}

if (condition) {
    statements;
} else if (condition) {
    statements;
} else{
    statements;
}
 

Note: if statements always use braces {}. Avoid the following error-prone form:

if (condition) //AVOID! THIS OMITS THE BRACES {}!
    statement;

7.5.for Statements

A for statement should have the following form:

for (initialization; condition; update) {
    statements;
}

An empty for statement (one in which all the work is done in the initialization, condition, and update clauses) should have the following form:

for (initialization; condition; update);

When using the comma operator in the initialization or update clause of a for statement, avoid the complexity of using more than three variables. If needed, use separate statements before the for loop (for the initialization clause) or at the end of the loop (for the update clause).

7.6.while Statements

A while statement should have the following form:

while (condition) {
    statements;
}

An empty while statement should have the following form:

while (condition);

7.7.do-while Statements

A do-while statement should have the following form:

do {
    statements;
} while (condition);

7.8.switch Statements

A switch statement should have the following form:

switch (condition) {
	case ABC:
	    statements;
	    /* falls through */

	case DEF:
	    statements;
	    break;

	case XYZ:
	    statements;
	    break;

	default:
	    statements;
	    break;
}

Every time a case falls through (doesn't include a break statement), add a comment where the break statement would normally be. This is shown in the preceding code example with the /* falls through */ comment.

Every switch statement should include a default case. The break in the default case is redundant, but it prevents a fall-through error if later another case is added.

7.9.try-catch Statements

A try-catch statement should have the following format:

try {
    statements;
} catch (Exception_Class $e) {
    statements;
}

8.White spaces

8.1.Blank Lines

Blank lines improve readability by setting off sections of code that are logically related.

Two blank lines should always be used in the following circumstances:

One blank line should always be used in the following circumstances:

8.2.Blank Spaces

Blank spaces should be used in the following circumstances:

       while (true) {
           ...
       }
    $a += $c + $d;
    $a = ($a + $b) / ($c * $d);
    
    while ($d++ = $s++) {
        $n++;
    }
    print_size("size is " + $foo + "\n");
    for (expr1; expr2; expr3)
    my_method((string) $aNum, (string) $x);
    my_method((int) ($cp + 5), ((int) ($i + 3)) 
                                  + 1);

9.Naming conventions

9.1.Classes and Interfaces

Class names should be nouns, first letter of each internal word capitalized, words separated by underscore (_). Try to keep your class names simple and descriptive. Use whole words-avoid acronyms and abbreviations (unless the abbreviation is much more widely used than the long form, such as URL or HTML).

Examples: class Form, class Guarded_Form.

9.2.Methods

Methods should be verbs, in lower case, words separated by underscore;

Example: public function calculate_total($customer_id);

9.3.Variables

Variables should be in lower case, words separated by underscore.

Example: $customer_total = $acc->calculate_total($customer_id);

9.4.Constants

Constants (defined with define()) should be in upper case, words separated by underscore.

Example: define('MY_CONSTANT', 5);

Class constants (defined with const) should be in upper case, words separated by underscore.

Example:

class Some_Class {

const $my_const = 5;

10.Programming Practices

10.1.Providing Access to Instance and Class Variables

Don't make any instance or class variable public without good reason. In general avoid usage of public class members.

10.2.Referring to static Class Methods

Avoid using an object to access a class (static) variable or method. Use a class name instead. For example:

Some_Class::class_static_method();      //OK
an_object->class_static_method();    //AVOID!

10.3.Constants

Numerical constants (literals) should not be coded directly, except for -1, 0, and 1, which can appear in a for loop as counter values.

10.4.Miscellaneous Practices

10.4.1.Parentheses

It is generally a good idea to use parentheses liberally in expressions involving mixed operators to avoid operator precedence problems. Even if the operator precedence seems clear to you, it might not be to others-you shouldn't assume that other programmers know precedence as well as you do.

if ($a == $b && $c == $d)     // AVOID!
if (($a == $b) && ($c == $d)) // RIGHT

10.4.2.Returning Values

Try to make the structure of your program match the intent. Example:

if (booleanExpression) {
    return true;
} else {
    return false;
}

should instead be written as

return booleanExpression;

Similarly,

if (condition) {
    return $x;
}
return $y;

should be written as

return (condition ? $x : $y);

10.5.Expressions before `?' in the Conditional Operator

If an expression containing a binary operator appears before the ? in the ternary ?: operator, it should be parenthesized. Example:

($x >= 0) ? $x : -$x;

10.6.Special Comments

10.6.1.TODO – description

TODO comments should have following syntax:

// TODO – description what have to be done so code to be completed

or

/* TODO – long description what have to be done so code to be completed
that spans on multiple rows */

TODO comments should be used to mark places that are not yet finished to full extend.

Example:

	for($i=1; $i <= $max_c; $i++) {
		//TODO – put check to skip calculating balance when client
		// doesn't have any transactions
		$client->calculate_balance();
	}

10.6.2.XXX

Use XXX in a comment to flag something that is bogus but works.

10.6.3.FIXME

Use FIXME in a comment to flag something that is bogus and broken.

11.Copyright notice and legal stuff

This document used as a base Code Conventions for the JavaTM programming Language” (http://java.sun.com/docs/codeconv). Although it is heavy modified any copying, adapting, and redistribing of this document have to comply with original copyright notice of Sun (http://java.sun.com/docs/codeconv/html/Copyright.doc.html).



Adapted with permission from CODE CONVENTIONS FOR THE JAVATM PROGRAMMING LANGUAGE. Copyright 1995-1999 Sun Microsytems, Inc. All rights reserved.



Java is trademark of Sun Microsystem.

All trademarks used in this documents are property of their respective owners and are used for identification purposes only.