Chapter 5. Coding Guidelines

Table of Contents

Code formatting and layout
General considerations
Indentation and line formatting
Naming
PHP code formatting
Documentation
Documentation blocks
Documentation tags
Coding
Overview
General PHP best practices
Error handling and exceptions
Cross platform issues
Security

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 UNKNOW3, 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.

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

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

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

    1. 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.

    2. If you modify a library you must document what you have changed (GPL requirement). Add your name as author / co-author to these modifications.

    3. The importance of the header is primarily to state that the code is GPL'ed. And remember only GPL compatible software is allowed to interface with FLOW3 (according to GPL itself).

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

    Example 5.1. The FLOW3 standard file header

    <?php
    declare(encoding = 'utf-8');
    
    /*                                                                         *
     * This script is part of the TYPO3 project - inspiring people to share!   *
     *                                                                         *
     * TYPO3 and UNKWON3 are free software; you can redistribute them and/or   *
     * modify them under the terms of the GNU General Public License version 2 *
     * as published by the Free Software Foundation.                           *
     *                                                                         *
     * 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 General       *
     * Public License for more details.                                        *
     *                                                                         */ 
    


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

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

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 5.2. Correct use of tabs and spaces

»   /*‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧*
»   ‧*‧Some‧comment‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧*
»   ‧*‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧*/

»   /**
»   ‧*‧Returns‧the‧name‧of‧the‧currently‧set‧context.
»   ‧*
»   ‧*‧@return‧string‧Name‧of‧the‧current‧context
»   ‧*‧@author‧Robert‧Lemke‧<robert@typo3.org>
»   ‧*/
»   public‧function‧getContext()‧{
»   »   return‧$this->context;
»   }



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.

Class names

Only the characters a-z, A-Z and 0-9 are allowed for class names – don't use special characters. The underscore sign "_" is allowed for separating the package name from the sub-package or component name from the sub-component name and so on.

All class names are written in UpperCamelCase, all uppercase names are allowed for well established abbreviations. Class names must be nouns, never adjectives.

A class name must start with the prefix "F3_". The name of the package containing the class follows, parts of the package hierarchy are seperated with underscores.

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

A few examples follow:

Example 5.3. Correct naming of classes

  • F3_FLOW3_Component

  • F3_FLOW3_Component_Manager

  • F3_MyPackage_MyComponent_MySubComponent

  • F3_MyPackage_MyComponent_MyHTMLParser

  • F3_Foo_Controller_Default

  • F3_MyPackage_MyComponent_AbstractLogger



Example 5.4. Incorrect naming of classes

  • myClass

  • F3_Urlwrapper

  • someComponent_classname

  • F3_MyPackage_MyComponentMySubComponent

  • F3_Foo_Controller_DefaultController



Interface names

Only the characters a-z, A-Z and 0-9 are allowed for interface names – don't use special characters. The underscore sign "_" is allowed for separating the package name from the interface name from the sub-component name and so on.

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.

An interface name must start with the prefix "F3_". The name of the package containing the interface follows, parts of the package hierarchy are seperated with underscores. A few examples follow:

Example 5.5. Correct naming of interfaces

  • F3_FLOW3_Component_Interface

  • F3_FLOW3_Component_ManagerInterface

  • F3_MyPackage_MyComponent_MySubComponentInterface

  • F3_MyPackage_MyComponent_MyHTMLParserInterface



Example 5.6. Incorrect naming of interfaces

  • myInterface

  • F3_Urlwrapper

  • IsomeComponent_classname

  • F3_FLOW3_Component_Manager_Interface



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 5.7. Correct naming of exceptions

  • F3_FLOW3_Component_Exception

  • F3_FLOW3_Component_Exception_InvalidClassName

  • F3_MyPackage_MyComponent_Exception

  • F3_MyPackage_MyComponent_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 5.8. 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 5.9. Correct naming of variables

  • $singletonObjectsRegistry

  • $argumentsArray

  • $aLotOfHTMLCode



Example 5.10. 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 might 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 5.11. 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.

Directory layout

The directory layout used for FLOW3 is shown below. Conventions for file names will be explained in it's own section below.

  • All directory names are UpperCamelCase.

Configuration

This directory contains the configuration files for the system. There should be only very few and small files here, as the majority of the configuration should be stored in the content repository.

FileCache

The FileCache directory holds copies of files stored in the content repository. They are stored locally (as seen from the webserver) to speed up delivery. The filecache directory itself contains only sub-directories which in turn hold either files or again sub-directories.

Public

The Public directory will always exist and stores copies if files for which no access restriction exists.

Packages

Packages can put their cache content below this directory, the next level directories are named after the package, in those the packages can reign freely.

Intranet

This is an example for a folder that contains files accessible only for requests authorized to fetch content from the "intranet" scope.

Packages

This directory contains sub-directories for all packages installed with the system. This includes packages delivered with the TYPO3 distribution as well as locally installed packages. Package directories contain further directories, some of which are mandatory.

[Package]
Classes

This directory contains the actual code for the package. Package authors are free to add (only!) class or interface files directly to this directory or to add another level to organize the content if necessary. All classes or interfaces below this directory are handled by the autolading mechanism and will be registered with the component manager automatically (and will thus be considered "components").

Documentation

Holds the package documentation. Please refer to the Documentor's Guide for more details about the directories and files within this directory.

Meta

Contains meta data about the package

PackageInfo.xml

Contains the basic information about the package, such as title, description, author, constraints, ...

Resources

Contains static resources the package needs, such as library code, template files, graphics, ...

Media

This directory holds images, PDF, Flash, CSS and other files that will be delivered to the client directly without further processing. The content of this directory will be copied into the content repository and propagated to the FileCache automatically by the package manager.

Templates

Template files used by the package should go here. If a user wants to modify the template it will end up elsewhere and should be pointed to by some configuration setting.

PHP

Should hold any PHP code that is an external library, PEAR or eZ component, should not be handled by the component manager (at least not by default), is of procedural nature or doesn't belong into the classes directory for any other reason.

Java

Should hold any Java code needed by the package. Repeat and rinse for Smalltalk, Modula, Pascal, ... ;)

More directories can be added as needed.

Tests

Holds the unit tests for the package

Files and file names

In addition to the directory naming rules laid out above there are also rules for naming the files inside those directories, of course. Here we go:

  • 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 configuration files must names start with configuration_

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

Here are some examples:

Example 5.12. File naming in FLOW3

  • F3_TemplateEngine_TemplateEngineInterface.php

    Contains the interface F3_TemplateEngine_TemplateEngineInterface which is part of the package F3_TemplateEngine

  • F3_Error_RuntimeException.php

    Contains the F3_Error_RuntimeException being a part of the package F3_Error

  • F3_DataAccess_Manager.php

    Contains class F3_DataAccess_Manager which is part of the package F3_DataAccess

  • F3_FLOW3_Package_Manager.php

    Contains the class F3_FLOW3_Package_Manager which is part of the package F3_FLOW3

  • 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 5.13. String literals

$vision = 'Inspiring people to share';


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

Example 5.14. 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 recommend to concatenate strings or use double quotes in the following form:

Example 5.15. Variable substitution

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


As you've seen in the previous example, we concatenate strings by using the dot operator. A space must be inserted before and after the dot for better readability:

Example 5.16. 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 5.17. Multi-line strings

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


Arrays

Classes

...

Example 5.18. Classes

class F3_MyPackage_MyComponent {

}



Functions and methods

if statements

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

  • ...

Example 5.19. if statements

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

if (allGoesWrong()) throw new Exception('Hey, all went wrong!');

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

} else {
   ...
}