Naposledy změněno 3. 12. 2007 Edituj Historie Poslední změny

Coding standard

This document describes rules and recommendations for developing applications and class libraries using the PHP language.

Common Naming Conventions

  • Always choose meaningful and specific names.
  • Avoid using abbreviations unless the full name is excessive.
  • Use uppercase for two-letter abbreviations, and Pascal Case for longer abbreviations.
  • When using camelCase or PascalCase, underscores are permitted.

PHP Files

  • For files that contain only PHP code, the closing tag (?>) is never permitted. Not including it prevents trailing whitespace from being accidentally injected into the output.
  • Use an indent of 4 spaces, with no tabs.
  • The recommended line length is 80 characters, i.e. developers should aim keep code as close to the 80-column boundary as is practical.
  • PHP code must always be delimited by the full-form PHP tags: <?php ... ?>
  • Always match class name and file name.

For all other files, only alphanumeric characters, underscores, and the dash character (-) are permitted. Spaces and are prohibited. Any file that contains any PHP code must end with the extension .php, or .phtml in case of templates.

Strings

When a string is literal (contains no variable substitutions), the single quote must always used to demarcate the string. Exception: when a literal string itself contains apostrophes, it is permitted to demarcate the string with double quotes.

Strings may be concatenated using the . operator. A space must always be added before and after the . operator to improve readability. It is permitted to break the statement into multiple lines – each successive line should be padded with whitespace such that the . operator is aligned under the = operator:

$sql = "SELECT `id`, `name` FROM `people` "
     . "WHERE `name` = 'Susan' "
     . "ORDER BY `name` ASC ";

Arrays

When declaring indexed arrays, a trailing space must be added after each comma delimiter to improve readability:

$sampleArray = array(1, 2, 3, 'test');

When declaring associative arrays, it is encouraged put each key and value pair on separated line, padded with 4 spaces. After last pair must be added comma.

$sampleArray = array(
    'firstKey'  => 'firstValue',
    'secondKey' => 'secondValue',
);

Classes

Naming conventions:

  • PascalCase
  • Use a noun or noun phrase for class name.
  • Add an appropriate class-suffix when sub-classing another type when possible.
  • Prefix class names with namespace.
  • Examples: TexyParser, NHttpRequest

Coding Style:

  • The brace is always written on the line underneath the class name.
  • Every class must have a documentation block that conforms to the PHPDocumentor standard.
  • Any code within a class must be indented four spaces.

Placing additional code in a class file is permitted but discouraged (static constructor calling is allowed). In these files, two blank lines must separate the class from any additional PHP code in the file.

Class members implementation must follow this order:

  1. Member Variables
    1. public
    2. protected
    3. private
  2. Constructor, Destructor
  3. Properties
  4. Methods
    1. public
    2. protected
    3. private

The ultimate ancestor of all instantiable classes should be NObject. The ultimate ancestor of all uninstantiable classes should be NClass.

Interfaces

Interface classes must follow the same conventions as other classes, however must end with the word Interface. Example: DibiDriverInterface

Variables

Naming conventions:

  • camelCase
  • Variables and properties should describe an entity not the type or size.
  • Do not include the parent class name within a property name.

For class member variables that are declared as private, the first character of the variable name may be a single underscore to improve readability. This is the only acceptable usage of an underscore in a variable name. Member variables declared public or protected may never start with an underscore. The var construct is not permitted.

Variables should always be as verbose as practical. Terse variable names such as $i and $n are discouraged for anything other than the smallest loop contexts.

Variables must have documentation block with @var directive and specified type.

Properties

Properties are OOP enhancement provided by NObject. They must follow the same conventions as other variables. Accessors must be prefixed with either get or set (followed by upper case letter) and declared as public. Getter is required, setter is optional.

Example:

public function getName()

public function setName()

$obj->name

Constants

They must always have all letters capitalized, separated by underscore characters.

Example: CONTENT_TEXTUAL, FIELD_NUMERIC

Constants must be defined as class members by using the const construct. Defining constants in the global scope with define is permitted but discouraged.

Functions and Methods

Naming conventions:

  • camelCase
  • Try to use a verb or verb-object pair.
  • If method returns boolean, try to prefix name with „is“, „can“, „has“.
  • Names should be as verbose as is practical to enhance the understandability of code.
  • Examples: fetchPairs(), getElementById(), isSubmitted()

Functions in the global scope are permitted but strongly discouraged (except extension methods). It is recommended that these functions should be wrapped in a static class.

Methods must always declare their visibility by using one of the private, protected, or public constructs.

Like classes, the brace is always written on the line underneath the function name. There is no space between the function name and the opening parenthesis for the arguments.

This is an example of an acceptable function declaration in a class:

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function verb()
    {
        // entire content of function
        // must be indented four spaces
    }
}

The return value must not be enclosed in parentheses. This can hinder readability and can also break code if a method is later changed to return by reference.

Function and Method Usage

Function arguments are separated by a single trailing space after the comma delimiter. This is an example of an acceptable function call for a function that takes three arguments:

fooBar(1, 2, 3);

Call-time pass by-reference is prohibited.

For functions whose arguments permitted arrays, the function call may include the „array“ construct and can be split into multiple lines to improve readability. In these cases, the standards for writing arrays still apply:

fooBar(array(1, 2, 3), 2, 3);

fooBar(1, 2, array(
    'firstKey'  => 'firstValue',
    'secondKey' => 'secondValue',
), 3, 4);

Extension Methods

Extension methods are OOP enhancement provided by NObject. They must follow the same conventions as other methods, but they are declared in the global scope and prefixed with {Class name}_prototype_. First parameter must have object type hint.

Example:

function MyClass_prototype_newMethod(MyClass $obj)

Control Statements

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.

The opening brace is written on the same line as the conditional statement. The closing brace is always written on its own line. Any content within the braces must be indented four spaces.

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

For „if“ statements that include „elseif“ or „else“, the formatting must be as in these examples:

if ($a != 2) {
    $a = 2;
} elseif ($a == 3) {
   $a = 4;
} else {
   $a = 7;
}

Control statements written with the „switch“ construct must have a single space before the opening parenthesis of the conditional statement, and also a single space after the closing parenthesis.

All content under each „case“ (or default) statement must be indented four spaces.

switch ($numPeople) {
case 1:
    break;

case 2:
    break;

default:
    break;
}

It is sometimes useful to write a case statement which falls through to the next case by not including a break or return in that case. To distinguish these cases from bugs, any case statement where break or return are omitted must contain the comment „// break intentionally omitted“.

Databases

  • Use alphanumeric characters.
  • Choose one way for all identifiers:
    1. use lowercase words and underscore _ to separate words
    2. or use camelCaps
  • Choose short, unambiguous names, using no more than one or two words.
  • Avoid abbreviated, concatenated, or acronymic names.

Tables:

  • Use plural table names.
  • Prefix lookup tables with the name of the table they relate to (e.g. order_status or orderStatus, order_type, etc.)
  • For junction table (which handle many to many relationships), concatenate the names of the two tables: {linking-table}_2_{related-table}

Columns:

  • Use singular column names.
  • Don't prefix columns names with table name.
  • The primary keys must have name id.
    • If more than one field makes up the key, suffix all of them with id (or pk?)
  • Foreign key names should be the referenced table name in singular suffixed with id.
    • Makes the table to which they refer completely obvious.
    • If there are multiple foreign keys referencing same table, prefix the foreign key name with an appropriately descriptive adjective (e.g. lead_person_id / leadPersonId, technical_person_id / technicalPersonId, etc. which transparently reference id in the persons table).
  • List the primary key first in a table, followed by foreign keys.
  • Boolean fields should be given names like is_deleted (or isDeleted), has_permission (or hasPermission). If the field holds date and/or time information, the word date or time should appear somewhere in the field name.

Views:

  • Follow the same rules that apply to naming tables with some exceptions:
  • A view can be a combination of more tables based on a join condition, thus, effectively representing two entities. In this case, consider combining the names the base tables.

SQL coding style:

  • Don't use the proprietary version and destroy portability (INSERT INTO ... VALUES vs. INSERT ... SET)
  • Format SQL to multiple lines:
SELECT *
FROM [customers]
WHERE [name] LIKE 'Peter%'
ORDER BY [name]

Myths of prefixing columns names with table name

  • prevents field names clashing with reservered words → refering by tablename.fieldname prevents much better
  • creates near unique field names, often simplifying query design and SQL coding → refering by tablename.fieldname does the same job
  • maintains semantic transparency of field names when using table aliases (e.g. SELECT a.activity_name FROM activity a) → Definitely not. What about two same tables in join? Refering by alias.fieldname is right way.

Datatypes is MySQL: