Skip to content

Dev.Coding Standard PHP Pi

Taiwen Jiang edited this page Aug 6, 2013 · 14 revisions

Selected PHP Coding Standard for Pi Engine

Check full version for details.

  • Omit the closing tag ?> for files containing only PHP code.

  • Indentation MUST consist of 4 spaces, not tabs.

  • Maximum line length is 80 characters, no exceeding of 120 characters.

  • Line termination use Unix convention with single Linefeed (LF).

  • Lines MUST NOT have whitespace characters preceding the LF character.

  • Successive capitalized letters are not allowed in namespaces and classes.

  • Abstract class names SHOULD begin with the term Abstract.

  • Interface MUST be nouns or adjectives and interface class names SHOULD end with the term Interface.

  • Spaces are strictly prohibited in file names.

  • Function/method names MUST contain only alphanumeric characters. Underscores are not permitted.

  • Function/method names MUST always start with a lowercase letter with "camelCase" formatting.

  • Variable names MUST contain only alphanumeric characters. Underscores are not permitted.

  • Variable names MUST always start with a lowercase letter with "camelCaps" convention.

  • Variables should always be as verbose as practical. Terse variable names such as $i and $n are discouraged and only for a loop less than 20 lines of code.

  • Constant names MUST be capitalized, while all words MUST be separated by underscore characters.

  • Short tags <? ?> MUST NOT be used within Pi code.

  • When a string is literal, the apostrophe or "single quote" SHOULD be used.

  • Variable substitution SHOULD use the form $greeting = "Hello ${name}, welcome back!";.

  • When concatenating strings with the "." operator, each successive line SHOULD be padded with white space such that the "." operator is aligned under the "=" operator:

$sql = "SELECT {{id}}, {{name}} FROM {{people}} "
     . "WHERE {{name}} = 'Susan' "
     . "ORDER BY {{name}} ASC ";
$sampleArray = array('firstKey'  => 'firstValue',
                     'secondKey' => 'secondValue');
  • Multi-line indexed arrays with first element on the same line: each successive line MUST be padded with spaces such that the beginning of each line is aligned with the initial element of the array:
$sampleArray = array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500);
  • Multi-line indexed arrays with first element on a new line: it MUST be padded at one indentation level greater than the line containing the array declaration, and all successive lines MUST have the same indentation and use a trailing comma for the last item in the array; the closing paren MUST be on a line by itself at the same indentation level as the line containing the array declaration:
$sampleArray = array(
    1, 2, 3, 'Zend', 'Studio',
    $a, $b, $c,
    56.44, $d, 500,
);
$sampleArray = array(
    'firstKey'  => 'firstValue',
    'secondKey' => 'secondValue',
);
  • A single empty line is required between a file-level documentation docblock and namespace declaration.

  • Every class MUST have a documentation block that conforms to the PHPDocumentor standard.

  • For line length exceeds the maximum line length, break the line after implements keywords, and pad those lines by one indentation level.

class SampleClass extends AbstractFoo implements
    Bar
{
}
  • For argument list exceeds the maximum line length, additional arguments to a function or method MUST be indented one additional level beyond the function or method declaration. A line break MUST occur before the closing argument paren, which MUST be placed on the same line as the opening brace of the function or method with one space separating the two, and at the same indentation level as the function or method declaration.
/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar($arg1, $arg2, $arg3,
        $arg4, $arg5, $arg6
    ) {
        // all contents of function
        // must be indented four spaces
    }
}

Closure definitions generally follow the same rules as for functions and methods:

  • Space MUST NOT be inserted between the "function" keyword and the opening parenthesis for the arguments.
  • A space MUST be added between any "use" statement used in declaration and the opening parenthesis for its arguments.
  • In cases where the argument list exceeds the maximum line length, you MAY introduce line breaks. Additional arguments to the function or method MUST be indented one additional level beyond the function or method declaration. A line break MUST occur before the closing argument paren, which MUST be placed on the same line as the opening brace of the function or method with one space separating the two, and at the same indentation level as the function or method declaration.
  • Call-time pass-by-reference MUST NOT be used.
  • The return value MUST NOT be enclosed in parentheses. This can hinder readability, in addition to breaking code if a method is later changed to return by reference.

The primary difference is that closures MUST retain the initial brace on the same line in which they are defined (not the following line). Code MUST be indented one additional level.

/**
 * Opening brace:
 */
$foo = function($x)
{
    // WRONG
};
 
$foo = function($x) {
    // RIGHT
};
 
/**
 * Use statement declaration
 */
$foo = function($x) use($y) {
    // WRONG
};
 
$foo = function($x) use ($y) {
    // RIGHT
};
 
/**
 * Indentation
 */
$foo = array_map(function($x) {
// WRONG
return strtolower($x);
}, $array);
 
$foo = array_map(function($x) {
    // RIGHT
    return strtolower($x);
}, $array);

Function and Method Usage

Function arguments MUST be separated by a single trailing space after the comma delimiter. The following is an example of an acceptable invocation of a function that takes three arguments:

threeArguments(1, 2, 3);

Call-time pass-by-reference MUST NOT be used. See the function declarations section for the proper way to pass function arguments by-reference.

In passing arrays as arguments to a function, the function call MAY include the array declaration and MAY be split into multiple lines to improve readability. In such cases, the normal guidelines for writing arrays still apply:

threeArguments(array(1, 2, 3), 2, 3);
 
threeArguments(array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500), 2, 3);
 
threeArguments(array(
    1, 2, 3, 'Zend', 'Studio',
    $a, $b, $c,
    56.44, $d, 500
), 2, 3);

Control Statements

If/Else/Elseif

Control statements based on the if and elseif constructs MUST have a single space before the opening parenthesis of the conditional and a single space after the closing parenthesis.

Within the conditional statements between the parentheses, operators MUST be separated by spaces for readability. Inner parentheses SHOULD be used to improve logical grouping for larger conditional expressions.

The opening brace MUST be written on the same line as the conditional statement if the conditional statement does not contain a line feed. The closing brace MUST be written on its own line. Any content within the braces MUST be indented using four spaces.

if ($a != 2) {
    $a = 2;
}

If the conditional statement causes the line length to exceed the maximum line length and has several clauses, you MUST break the conditional into multiple lines. In such a case, break the line prior to a logic operator, and pad the line such that it aligns under the first character of the conditional clause. The closing paren in the conditional will then be placed on a line with the opening brace, with one space separating the two, at an indentation level equivalent to the opening control statement.

if (($a == $b)
    && ($b == $c)
    || (Foo::CONST == $d)
) {
    $a = $d;
}

The intention of this latter declaration format is to prevent issues when adding or removing clauses from the conditional during later revisions.

For if statements that include elseif or else, the formatting conventions are similar to the if construct. The following examples demonstrate proper formatting for if statements with else and/or elseif constructs:

if ($a != 2) {
    $a = 2;
} else {
    $a = 7;
}
 
if ($a != 2) {
    $a = 2;
} elseif ($a == 3) {
    $a = 4;
} else {
    $a = 7;
}
 
if (($a == $b)
    && ($b == $c)
    || (Foo::CONST == $d)
) {
    $a = $d;
} elseif (($a != $b)
          || ($b != $c)
) {
    $a = $c;
} else {
    $a = $b;
}

PHP allows statements to be written without braces in some circumstances. This coding standard makes no differentiation; all if, elseif or else statements MUST use braces.

Switch

Control statements written with the switch statement MUST have a single space before the opening parenthesis of the conditional statement and after the closing parenthesis.

All content within the switch statement MUST be indented using four spaces. Content under each case statement MUST be indented using an additional four spaces.

switch ($numPeople) {
    case 1:
        break;
 
    case 2:
        break;
 
    default:
        break;
}

The construct default MAY be omitted from a switch statement, but the code MUST contain a comment indicating deliberate omission in such cases.

Inline Documentation

Documentation Format

All documentation blocks ("docblocks") MUST be compatible with the phpDocumentor format. Describing the phpDocumentor format is beyond the scope of this document. For more information, visit PHPDoc reference.

All class files MUST contain a "file-level" docblock at the top of each file and a "class-level" docblock immediately above each class. Examples of such docblocks can be found below.

General Notes

Classes and interfaces referenced by annotations MUST follow the same resolution order as PHP. In other words:

If the class is in the same namespace, simply refer to the class name without the namespace:

namespace Foo\Component;
 
class Bar
{
    /**
     * Assumes Foo\Component\Baz:
     * @param Baz $baz
     */
    public function doSomething(Baz $baz)
    {
    }
}

If the class is in a subnamespace of the current namespace, refer to it relative to the current namespace:

namespace Foo\Component;
 
class Bar
{
    /**
     * Assumes Foo\Component\Adapter\Baz:
     * @param Adapter\Baz $baz
     */
    public function doSomething(Adapter\Baz $baz)
    {
    }
}

If the class is imported, either via a namespace or explicit class name, use the name as specified by the import:

namespace Foo\Component;
 
use Zend\EventManager\EventManager as Events,
    Zend\Log;
 
class Bar
{
    /**
     * Assumes Zend\EventManager\EventManager and Zend\Log\Logger:
     * @param Events $events
     * @param Log\Logger $log
     */
    public function doSomething(Events $events, Log\Logger $log)
    {
    }
}

If the class is from another namespace, but not explicitly imported, provide a globally resolvable name:


namespace Foo\Component;
 
class Bar
{
    /**
     * Assumes \Zend\EventManager\EventManager:
     * @param \Zend\EventManager\EventManager $events
     */
    public function doSomething(\Zend\EventManager\EventManager $events)
    {
    }
}

Files

Every file that contains PHP code MUST have a docblock at the top of the file that contains these phpDocumentor tags at a minimum:

/**
 * Pi Engine (http://pialog.org/)
 *
 * @link      http://code.pialog.org for the Pi Engine source repository
 * @copyright Copyright (c) Pi Engine (http://pialog.org/)
 * @license   http://www.pialog.org/license.txt New BSD License
 */

Classes

Every class MUST have a docblock that contains these phpDocumentor tags at a minimum:

/**
 * Short description for class
 *
 * Long description for class (if any)...
 *
 * Sample code:
 *
 * <code>
 *   $someCodeForUseExample;
 * </code>
 *
 * @author    [Author Name] <[author_email_address]>
 */

Note: Change above author name and email to your own.

Functions

Every function, including object methods, MUST have a docblock that contains at a minimum:

A description of the function

  • All of the arguments
  • All of the possible return values (even void) It is not necessary to use the @access annotation because the access level is already known from the public, private, or protected visibility modifier used to declare the function.

If a function or method may throw an exception, use @throws for all known exception classes:

@throws exceptionclass [description]
Clone this wiki locally