Photo: Steve Kay

CGL on one page

The most important parts of the CGL distilled into one page. Does it get better than that?
Appendix A. Coding Guidelines

Coding Standards are an important factor for achieving a high code quality. A common visual style, naming conventions and other technical settings allow us to produce a homogenous code which is easy to read and maintain. However, not all important factors can be covered by rules and coding standards. Equally important is the style in which certain problems are solved programmatically - it's the personality and experience of the individual developer which shines through and ultimately makes the difference between technically okay code or a well considered, mature solution.

These guidelines try to cover both, the technical standards as well as giving incentives for a common development style. These guidelines must be followed by everyone who creates code for the FLOW3 core. Because TYPO3 is based on FLOW3, it follows the same principles - therefore, whenever we mention FLOW3 in the following sections, we equally refer to TYPO3. We hope that you feel encouraged to follow these guidelines as well when creating your own packages and FLOW3 based applications.

A.1. Code formatting and layout

aka "beautiful code"

The visual style of programming code is very important. In the TYPO3 project we want many programmers to contribute, but in the same style. This will help us to:

  • Easily read/understand each others code and consequently easily spot security problems or optimization opportunities

  • It is a signal about consistency and cleanliness, which is a motivating factor for programmers striving for excellence

Some people may object to the visual guidelines since everyone has his own habits. You will have to overcome that in the case of FLOW3; the visual guidelines must be followed along with coding guidelines for security. We want all contributions to the project to be as similar in style and as secure as possible.

General considerations

  • Almost every PHP file in FLOW3 contains exactly one class and does not output anything if it is called directly. Therefore you start your file with a <?php tag and end it with the closing ?>.

  • Every file must contain a header stating encoding, namespace, copyright and licensing information

    1. Declare your namespace. The namespace must start with "F3"!

    2. Because it is likely that more than one person will work on a class in the long run, we recommend adding a copyright statement like “Copyright belongs to the respective authors” and add yourself to the list of authors for the methods you implemented or changed (significantly).

    3. The copyright header itself must not start with /**, as this may confuse documentation generators!

    Example A.1. The FLOW3 standard file header

    <?php
    declare(ENCODING = 'utf-8');
    namespace F3\Your\Stuff\Here;
    
    /*                                                                        *
     * This script belongs to the FLOW3 framework.                            *
     *                                                                        *
     * It is free software; you can redistribute it and/or modify it under    *
     * the terms of the GNU Lesser General Public License as published by the *
     * Free Software Foundation, either version 3 of the License, or (at your *
     * option) any later version.                                             *
     *                                                                        *
     * This script is distributed in the hope that it will be useful, but     *
     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-    *
     * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser       *
     * General Public License for more details.                               *
     *                                                                        *
     * You should have received a copy of the GNU Lesser General Public       *
     * License along with the script.                                         *
     * If not, see http://www.gnu.org/licenses/lgpl.html                      *
     *                                                                        *
     * The TYPO3 project - inspiring people to share!                         *
     *                                                                        */


  • Code lines are of arbitrary length, no limitations to 80 characters or something similar (wake up, graphical displays have been available for decades now...)

  • Lines end with a newline a.k.a chr(10) - UNIX style

  • Files must be encoded in UTF-8

Make sure you use the correct license and mention the correct package in the header, See http://forge.typo3.org/wiki/flow3-overview/Licensing_boilerplates_to_use_with_your_code for some boilerplate text.

Indentation and line formatting

Indentation is done with tabs - and not spaces! The beginning of a line is the only place where tabs are used, in all other places use spaces. Always trim whitespace off the end of a line.

Here's a code snippet which shows the correct usage of tabs and spaces:

Example A.2. Correct use of tabs and spaces

/**
 * Returns the name of the currently set context.
 *
 * @return string Name of the current context
 * @author Your Name <your@email.here>
 */
public function getContextName() {
»   return $this->contextName;
}



There seem to be very passionate opinions about whether TABs or spaces should be used for indentation of code blocks in the scripts. If you'd like to read more about this religious discussion, you find some nice arguments in the Joels on Software forum.

Naming

Naming is a repeatedly undervalued factor in the art of software development. Although everybody seems to agree on that nice names are a nice thing to have, most developers choose cryptic abbreviations in the end (to save some typing). Beware that we TYPO3 core developers are very passionate about naming (some people call it fanatic, well ...). In our opinion spending 15 minutes (or more ...) just to find a good name for a method is well spent time! There are zillions of reasons for using proper names and in the end they all lead to better readable, manageable, stable and secure code.

  • As a general note, english words (or abbreviations if neccessary) must be used for all class names, method names, comments, variables names, database table and field names. Although PHP6 allows for using funny japanese, tibetian or don't-know-what characters, the consensus is that english is much better to read for the most of us.

  • If acronyms or abbreviations are embedded in names, keep them in the case they usually are, i.e. keep URL uppercase, also when used in a method name like getURLForLink(), ACMEManager etc.

Package names

All package names are written in UpperCamelCase. In order to avoid problems with different filesystems, only the characters a-z, A-Z and 0-9 are allowed for package names – don't use special characters.

Namespace and Class names

  • Only the characters a-z, A-Z and 0-9 are allowed for namespace and class names – don't use special characters.

  • All namespace and class names are written in UpperCamelCase, all uppercase names are allowed only for well established abbreviations.

  • The unqualified class name must be meant literally even without the namespace.

  • The main purpose of namespaces is categorization and ordering

  • Class names must be nouns, never adjectives.

  • The name of abstract classes should start with the word "Abstract".

A few examples follow:

Table A.1. Incorrect naming of namespaces and classes

Fully qualified class name Unqualified class nameRemarks
\F3\FLOW3\Session\PHPPHPThe class is not a representation of PHP!
\F3\FLOW3\Cache\Backend\FileFileThe class doesn't represent a file!
\F3\FLOW3\Session\InterfaceInterfaceNot allowed, "Interface" is a reserved keyword
\F3\Foo\Controller\DefaultDefaultNot allowed, "Default" is a reserved keyword


Table A.2. Correct naming of namespaces and classes

Fully qualified class nameUnqualified class nameRemarks
\F3\FLOW3\Session\PHPSessionPHPSessionThat's a PHP Session
\F3\FLOW3\Cache\Backend\FileBackendFileBackendA File Backend
\F3\FLOW3\Session\SessionInterfaceSessionInterfaceInterface for a session
\F3\Foo\Controller\StandardControllerStandardControllerThe standard controller


Table A.3. Edge cases in naming of namespaces and classes

Fully qualified class nameUnqualified class nameRemarks
\F3\FLOW3\Object\ManagerManagerIf it's the only manager in that namespace, it's okay
\F3\Foo\Bar\BuilderBuilderIf it's clear what the builder builds (Bar?), it's okay
\F3\FLOW3\Object\BuilderBuilderProblem: There's a "ConfigurationBuilder" in the same namespace, therefore better rename the Builder to ObjectBuilder
\F3\FLOW3\Object\FactoryFactoryAs long as it is the only factory in that namespace, okay
\F3\FLOW3\MVC\ControllerInterfaceControllerInterfaceConsequently the interface belongs to all the controllers in the Controller sub namespace
\F3\FLOW3\MVC\Controller\ControllerInterface Better
\F3\FLOW3\Cache\AbstractBackendAbstractBackendSame here: In reality this class belongs to the backends
\F3\FLOW3\Cache\Backend\AbstractBackend Better


Note

When specifying class names to PHP, always reference the global namespace inside namespaced code by using a leading backslash. When referencing a class name inside a string (e.g. given to the create-Method of the ObjectFactory, in pointcut expressions or in YAML files), never use a leading backslash. This follows the native PHP notion of names in strings always being seen as fully qualified.

Interface names

Only the characters a-z, A-Z and 0-9 are allowed for interface names – don't use special characters.

All interface names are written in UpperCamelCase, all uppercase names are allowed for well established abbreviations. Interface names must be adjectives or nouns and have the Interface suffix. A few examples follow:

Example A.3. Correct naming of interfaces

  • \F3\FLOW3\Object\ObjectInterface

  • \F3\FLOW3\Object\ManagerInterface

  • \F3\MyPackage\MyObject\MySubObjectInterface

  • \F3\MyPackage\MyObject\MyHTMLParserInterface



Exception names

Exception naming basically follows the rules for naming classes. There are two possible types of exceptions: Generic exceptions and specific exceptions. Generic exceptions should be named "Exception" preceeded by their namespace. Specific exceptions should reside in their own sub-namespace and must not contain the word Exception.

Example A.4. Correct naming of exceptions

  • \F3\FLOW3\Object\Exception

  • \F3\FLOW3\Object\Exception\InvalidClassName

  • \F3\MyPackage\MyObject\Exception

  • \F3\MyPackage\MyObject\Exception\OutOfCoffee



Method names

All method names are written in lowerCamelCase, all uppercase names are allowed for well established abbreviations. In order to avoid problems with different filesystems, only the characters a-z, A-Z and 0-9 are allowed for method names – don't use special characters.

Make method names descriptive, but keep them concise at the same time. Constructors must always be called __construct(), never use the class name as a method name.

A few examples:

Example A.5. Correct naming of methods

  • myMethod()

  • someNiceMethodName()

  • betterWriteLongMethodNamesThanNamesNobodyUnderstands()

  • singYMCALoudly()

  • __construct()



Variable names

Variable names are written in lowerCamelCase and should be

  • self-explaining

  • not shortened beyond recognition, but rather longer if it makes their meaning clearer

The following example shows two variables with the same meaning but different naming. You'll surely agree the longer versions are better (don't you ...?).

Example A.6. Correct naming of variables

  • $singletonObjectsRegistry

  • $argumentsArray

  • $aLotOfHTMLCode



Example A.7. Incorrect naming of variables

  • $sObjRgstry

  • $argArr

  • $cx



As a special exception you may use variable names like $i, $j and $k for numeric indexes in for loops if it's clear what they mean on the first sight. But even then you should want to avoid them...

Constant names

All constant names are written in UPPERCASE. This includes TRUE, FALSE and NULL. Words can be separated by underscores - you can also use the underscore to group constants thematically:

Example A.8. Correct naming of constants

  • STUFF_LEVEL

  • COOLNESS_FACTOR

  • PATTERN_MATCH_EMAILADDRESS

  • PATTERN_MATCH_VALIDHTMLTAGS



It is, by the way, a good idea to use constants for defining regular expression patterns (as seen above) instead of defining them somewhere in your code.

File names

These are the rules for naming files:

  • All file names are UpperCamelCase.

  • Class and interface files are named according to the class or interface they represent

  • Each file must contain only one class or interface

  • Names of files containing code for unit tests must be the same as the class which is tested, appended with "Test.php".

  • Files are placed in a directory structure representing the namespace structure.

Here are some examples:

Example A.9. File naming in FLOW3

  • TemplateEngine/TemplateEngineInterface.php

    Contains the interface \F3\TemplateEngine\TemplateEngineInterface which is part of the package \F3\TemplateEngine

  • Error/RuntimeException.php

    Contains the \F3\Error\RuntimeException being a part of the package \F3\Error

  • DataAccess/Manager.php

    Contains class \F3\DataAccess\Manager which is part of the package \F3\DataAccess

  • FLOW3/Package/Manager.php

    Contains the class \F3\FLOW3\Package\Manager which is part of the package \F3\FLOW3

  • Package/ManagerTest.php

    Contains the class \F3\FLOW3\Package\ManagerTest which is a test case for PHPUnit.



PHP code formatting

Strings

In general, we use single quotes to enclose literal strings:

Example A.10. String literals

$vision = 'Inspiring people to share';


If the string itself contains single quotes or apostrophes, we use double quotes:

Example A.11. String literals enclosed by double quotes

$message = "'Kasper' is the name of the friendly ghost.";


If you'd like to insert values from variables, we prefer to concatenate strings:

Example A.12. Variable substitution

$message = 'Hey ' . $name . ', you look ' . $look . ' today!';


A space must be inserted before and after the dot for better readability:

Example A.13. Concatenated strings

$vision = 'Inspiring people ' . 'to share.';


You may break a string into multiple lines if you use the dot operator. You'll have to indent each following line to mark them as part of the value assignment:

Example A.14. Multi-line strings

$vision = 'Inspiring' .
   'people ' .
   'to ' .
   'share';


Arrays

Classes

...

Example A.15. Classes

namespace F3\MyPackage;

class MyObject {

}



Functions and methods

if statements

  • There needs to be one space between the if keyword and the opening brace "(" of the test expression

  • After the closing brace ")" of the test expression follows one space before the curly brace "{"

  • else and elseif are on the same line as their corresponding curly braces

Example A.16. if statements

if ($something || $somethingElse) {
   doThis();
} else {
   doSomethingElse();
}

if (allGoesWrong() === TRUE) throw new \Exception('Hey, all went wrong!', 123);

if (weHaveALotOfCriteria() === TRUE
   && notEverythingFitsIntoOneLine() === TRUE
   || youJustTendToLikeIt() === TRUE) {
      doThis();

} else {
   ...
}