Search
Table of ContentsDeveloper's Manual
Creating translations Index API documentation

## Coding Principles

### General introduction

"Coding principles" are general rules on how to write and format PHP-code. These rules are meant to help, to keep your source code easy to read and understand.

If several authors are working together on the same source code, it is quite common, that each author may have it's own idea on how clean code should look like. There are dozens of possibilities to express the same thing with PHP. To ensure the source code remains well readable in the long term, it is necessary that all authors agree on a common standard on how to write statements.

The "Coding principles" stated here provide such a definition. These rules are not obligating, however, I would like to recommend them to you.

### Indention and comments

The source code should be indented with 4 blanks. Do not use tabulators, because these can be viewed differently on different systems.

For comments use exclusively the syntax /* comment */. This has a deeper meaning! Later, when you write or use scripts, that analyse or automatically document your source code, this will make your task a lot easier. Unlike the syntax // comment or # comment, you have a fixed start and end for each comment, that you can rely on. Lines of comments can be fetched easily with simple regular expressions, saving you much effort when creating these scripts.

Here is a example.

    <?php
    $output = array();
    /* iterate through input */
    foreach ($input as $key => $element)
    {
        $element = strip_tags( (string) $element);
        if (preg_match("/\//", $key)) {
            $key = preg_replace("/\//", ".", $key);
            Hashtable::set($output, $key, $element);
        } else {
            $output[$key] = $element;
        }
    } /* end foreach */
    ?>

### Declarations and lifetime of variables

In PHP has no variable declaration in the sense of other languages. Nevertheless variables have a certain life span. Before and after a variable's life span it does not exist, what means no value is assigned.

The reason for many errors in PHP is, that programmers assume a variable to be unused, of a certain type, or that is no longer used after a certain code line. However PHP does NOT ensure that and also will not warn you if you are wrong, unless you "please" it to do so. This is exactly what you should do!

If you do it, PHP will warn you, if you use a variable outside it's life span and by doing so will possibly save you many hours of debugging!

Variables should be named in CamelCase - for example, $debugSourcePath instead of $debug_source_path. The first letter should always be written small - in difference to class names. There (and only there) the first letter should be large. This definition for the way of writing is similar to that in many other languages like Java.

    <?php
    /* Start of life span */
    /* The following line will warn you if the variable already exists */
    assert('!isset($variable); // Cannot redeclare $variable');

    /* always initialize variables before use */
    $variable = 0;

    /* ... additional statements ... */

    /* If a variable is no longer needed it should always explicitely be unset */
    unset($variable);
    /* End of life span */
    ?>

### If and Else statements

When working with if and else, please always use brackets { } for each block. While PHP permits to spare these brackets, if a block consists of only one statement, this style of coding is error-prone, since you may always come to the point where you decide to add another line of code and in this situation it is easy to oversee the missing brackets.

If an If-block is very long (more than 10 lines), you should add a comment /* end if */ at the closing bracket for better readability. For long code blocks this helps to identify what statement a bracket belongs to.

    <?php
    if ($test1) {
        /* ... */
    } elseif ($test2) {
        /* ... */
    } else {
        /* ... */
    } /* end if */
    ?>

### Switch statement

When using Switch-statements mind the text indentation and line breaks, which serve readability.

Avoid using "fall trough", for this may lead to code which is difficult to read. If you somehow cannot avoid it, you should mark this special case with the comment /* fall through */ instead of the Break-statement for documentation.

The Default-case should always be included. This enhances the clearity of your code.

If two different cases use the same code, this can be expressed by writing case 1: case 2: ... break;. This is a usefull abbreviation and you are recommended to use it, where you see fit.

    <?php
    switch ($variable)
    {
        case 1:
            /* ... */
        break;
        case 2: case 3:
            /* ... */
        break;
        case 4:
            /* ... */
        break;
        case 5:
            /* ... */
        break;
        case 6:
            /* ... */
        /* fall through */
        default:
            /* ... */
        break;
    } /* end switch */
    ?>

### For, Foreach and While statements

Again mind the line breaks for better readability.

PHP has a rather uncommon "feature". The life span of a block / loop -variable does NOT end, as in other languages, when exiting the block / loop, but will continue to have it's last assigned value. This also means that loop variables in PHP may overwrite the value of another, already existing variable. PHP will not warn you on this issue. To address this behavior, and the potential risk, which is associated´with it, you should treat the begin of any For- or ForEach-loop like a variable declaration and check whether any used loop variables already exist. When exiting a loop, you should always explicitly unset variables to avoid side effects.

Note that a ForEach statement necessarily expects an array to work on. Before entering the loop check the type of the input variable by using the function is_array () and add appropriate error handling if the variable has not the expected type.

For While-loops ensure that exit points, introduced by Break- or Continue-statements, are always sufficiently documented.

Take a look at the following examples:

    <?php
    /* Example: FOR-loop */
    assert('!isset($i); // Cannot redeclare $i');
    for ($i = 0; $i < sizeOf($input); $i++)
    {
        /* ... */
    } /* end for */
    unset($i);

    /* Example: FOREACH-loop */
    assert('!isset($key); // Cannot redeclare $key');
    assert('!isset($element); // Cannot redeclare $element');
    foreach ($input as $key => $element)
    {
        /* ... */
    } /* end foreach */
    unset($key);
    unset($element);

    /* Example: WHILE-loop */
    while ($test)
    {
        /* ... */
    } /* end while */
    ?>

### Classes and functions

For the names of classes and functions be advised to uniformly use CamelCase. For function names, the first letter is always small.. For class names the first letter is always capitalized. This rule is similar to Java and other C-type languages.

For backward compatibility, you should use PHP4 syntax, if possible. However, if you need upward-compatibility to PHP6, you should use PHP5 syntax instead.

In PHP4 it is (or was) common that the names of private functions and methods start with an underscore, for example: "_foo()". While there is no need to do that for PHP5 anymore, it may still help to enhance the readability of the source code. For reasons of readability: use this notation (IF you use it) only for identification of private functions and methods.

It also has become quite common, that the name of a function starts with a verb in imperative and a noun in singular, for example: "getBeer()" or "setContent()". While this is not always possible, you should still try to use this notation where it makes sense, as this usually improves readability of your code.

Use PHPDoc comments (http://www.phpdoc.org/) for documentation of classes and functions. These should be mandatory. Make it a habit to always immediately document any new function you write, while the idea and details are still fresh in your memory. By writing documentation you are forced to review your work and possibly even recognize mistakes or defective conditions in this early stage of development.

The documentation of a function should always contain: the input data the function expects (for example: "an integer between 0 and 5"), the purpose of the function - that is what this does. oreover, the return values of the function (for example: "an integer between 1 and 6, or false, if an error occurs").

It is general practice to document source codes in English. If you are able to write your documentation in English, then do so.

If you want to use UML-style stereotypes, then write them in front of the name of the function or class and use parentheses, which is common for writing stereotypes.

It is common to keep variables "private" and the restrict all access to set - and get-functions. For example, access to a private variable "$foo" should be restricted to functions with the name "setFo ()" and "getFoo()". This rule applies by analogy to other languages, such as Java. Note that the class variables must always be initialized - if necessary, initialize them with the constant "null"! While PHP allows you not to do this, the function "get_class_vars()" for example, would not find these uninitialized variables as class variables when using PHP < 4.2, which may cause unexpected behavior for your code.

    <?php
    /**
     * «Stereotype» name
     *
     * The purpose of this class is ...
     *
     * @access      public
     * @package     package
     * @subpackage  subpackage
     */
    class MyClass extends BaseClass
    {

        /**#@+
         * @access  private
         */

        /** @var array */  var $var1 = array();
        /** @var int   */  var $var2 = 0;
        /** @var View  */  var $var3 = null;
        /** @var array */  var $var4 = array();
        /** @var array */  var $var5 = array();

        /**#@-*/

        /**
         * «Stereotyp» Constructor
         *
         * This function accepts the following input ...
         *
         * This function does ...
         *
         * It returns the following values ...
         *
         * @param  string  $filename  path to file.ext
         */
        function MyClass ($filename)
        {
            /* ... */
        }

        /**
         * «Stereotype» name
         *
         * This function accepts the following input ...
         *
         * This function does ...
         *
         * It returns the following values ...
         *
         * @access  public
         * @param   string  $id  alpha-numeric, unique identifier
         * @return  int
         */
        function getVar ($filename)
        {
            /* ... */
        }

    }
    ?>

Creating translations Index API documentation

Thomas Meyer, www.yanaframework.net