diff --git a/docs/en/05_Contributing/14_PHP_Coding_Conventions.md b/docs/en/05_Contributing/14_PHP_Coding_Conventions.md index 63612242f..94754b0d4 100644 --- a/docs/en/05_Contributing/14_PHP_Coding_Conventions.md +++ b/docs/en/05_Contributing/14_PHP_Coding_Conventions.md @@ -9,365 +9,47 @@ and facilitate collaboration by making code more consistent and readable. If you are unsure about a specific standard, imitate existing SilverStripe code. -## File Formatting - -### Indentation - -Always use hard tabs rather then spaces for indentation, with one tab per nesting level. - -### Maximum Line Length - -The target line length is 100 columns with tabs being treated as four columns, -meaning developers should strive keep each line of their code -under 80 columns where possible and practical. -However, longer lines are acceptable in some circumstances. -The maximum length of any line of PHP code is 120 columns. - -### Line Termination - -Line termination follows the Unix text file convention. Lines must end with a single linefeed (LF) character. -Linefeed characters are represented as ordinal 10, or hexadecimal 0x0A. -Note: Do not use carriage returns (CR) as is the convention in Apple OS's (0x0D) or the carriage return - -linefeed combination (CRLF) as is standard for the Windows OS (0x0D, 0x0A). - -## Naming Conventions - -Class, function, variable and constant names may only contain alphanumeric characters and underscores. +## PSR-2 +Starting with SilverStripe 4.x, our goal is [PSR-2 Coding Standards](http://www.php-fig.org/psr/psr-2/) compliance. +Since this affects existing APIs, some details like method casing will be iterated on in the next releases. +For example, many static methods will need to be changed from lower underscore to lower camel casing. + ## Spelling All symbols and documentation should use UK-English spelling (e.g. "behaviour" instead of "behavior"), except when necessitated by third party conventions (e.g using PHP's `Serializable` interface). -### Classes +## Configuration Variables -Class and filenames are in `UpperCamelCase` format: +SilverStripe's [Config API]() can read its defaults from variables declared as `private static` on classes. +As opposed to other variables, these should be declared as lower case with underscores. :::php - class MyClass {} - -If a class name is comprised of more than one word, the first letter of each -new word must be capitalized. Successive capitalized letters are used in -acronyms, e.g. a class `XMLImporter` is used while `XmlImporter` is not. - -### Methods - -Static methods should be in `lowercase_with_underscores()` format: - - :::php - public static function my_static_method() {} - -Action handlers on controllers should be in `completelylowercase()` format. -This is because they go into the controller URL in the same format (eg, `home/successfullyinstalled`). -Method names are allowed to contain underscores here, in order to allow URL parts with dashes -(`mypage\my-action` gets translated to `my_action()` automatically). - - :::php - public function mycontrolleraction() {} - -Object methods that will be callable from templates should be in `$this->UpperCamelCase()` format. -Alternatively, `$this->getUpperCamelCase()` will work the same way in templates - -you can access both coding styles as `$UpperCamelCase`. - -Other instance methods should be in `$this->lowerCamelCase()` format: - - :::php - public function myInstanceMethod() {} - -Methods inside classes must always declare their visibility by using one of the private, protected, or public modifiers. - -### Variables - -Static variables should be `self::$lowercase_with_underscores` - - :::php - self::$my_static_variable = 'foo'; - -Member variables should be `$this->lowerCamelCase` - - :::php - $this->myMemberVariable = 'foo'; - -Member variables always declare their visibility by using one of the private, protected, or public modifiers - -### Constants - -All letters used in a constant name must be capitalized, -while all words in a constant name must be separated by underscore characters. - - :::php - const INTEREST_RATE = 0.19; - - define('INTEREST_RATE', 0.19); - -Constants must be defined as class members with the `const` modifier. -Defining constants in the global scope with the `define` function is permitted but strongly discouraged. - -### File Naming and Directory Structure - -Classes need to be in a file of the same name. Multiple classes are allowed to be contained in one file, -as long as the prefix of the class equals the filename, and is separated by an underscore from the remaining name. -For example `MyClass` and `MyClass_Controller` will both need to be placed into `MyClass.php`. - -Example: `mysite/code/MyClass.php` - - :::php - 'firstValue', - 'secondKey' => 'secondValue'); - -Alternately, the initial array item may begin on the following line. -If so, it should be padded at one indentation level greater than the line containing the array declaration, -and all successive lines should have the same indentation; the closing paren should be on a line by itself at the -same indentation level as the line containing the array declaration. -For readability, the various "=>" assignment operators should be padded such that they align. - - :::php - $sampleArray = array( - 'firstKey' => 'firstValue', - 'secondKey' => 'secondValue', - ); - -### Function and Method Declaration - -No method or function invocation is allowed to have spaces directly -before or after the opening parathesis, as well as no space before the closing parenthesis. - - :::php - public function foo($arg1, $arg2) {} // good - public function foo ( $arg1, $arg2 ) {} // bad - -Keep the opening brace on the same line as the statement. - - :::php - // good - public function foo() { - // ... - } - - // bad - public function bar() + class MyClass { - // ... + private static $my_config_variable = 'foo'; } -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 should then occur before the closing argument paren, -which should then 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. - :::php - public function bar($arg1, $arg2, $arg3, - $arg4, $arg5, $arg6 - ) { - // indented code - } - -Function and method arguments should be separated by a single trailing space after the comma delimiter, -apart from the last argument. - -### Control Structures - -#### if/else/elseif - -No control structure is allowed to have spaces directly -before or after the opening parenthesis, as well as no space before the closing parenthesis. - -The opening brace and closing brace are written on the same line as the conditional statement. -Any content within the braces must be indented using a tab. - - :::php - if($a != 2) { - $a = 2; - } - -If the conditional statement causes the line length to exceed the maximum line length and has several clauses, -you may 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. - - :::php - 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: - - :::php - if($a != 2) { - $a = 2; - } elseif($a == 3) { - $a = 4; - } else { - $a = 7; - } - -Statements with `if` can be written without braces on a single line as the block, as long as no `else` statement exists. - - :::php - // good - if($a == $b) doThis(); - - // bad - if($a == $b) doThis(); - else doThat(); - -#### Prefer identical (===) comparisons over equality (==) +## Prefer identical (===) comparisons over equality (==) Where possible, use type-strict identical comparisons instead of loosely typed equality comparisons. Read more in the PHP documentation for [comparison operators](http://php.net/manual/en/language.operators.comparison.php) and [object comparison](http://php.net/manual/en/language.oop5.object-comparison.php). :::php // good - only need to cast to (int) if $a might not already be an int - if((int)$a === 100) doThis(); + if ((int)$a === 100) { + doThis(); + } // bad - if($a == 100) doThis(); - -#### switch - -All content within the "switch" statement must be indented using tabs. -Content under each "case" statement must be indented using an additional tab. - - :::php - switch($numPeople) { - case 1: - break; - case 2: - break; - default: - break; + if ($a == 100) { + doThis(); } -The construct `default` should never be omitted from a switch statement. -#### for/foreach/while - -Loop constructs follow the same principles as "Control Structures: if/else/elseif". - -### Separation of Logic and Presentation +## Separation of Logic and Presentation Try to avoid using PHP's ability to mix HTML into the code. @@ -419,20 +101,24 @@ Example: * * @package custom */ - class MyClass extends Class { + class MyClass extends Class + { - /** - * My Method. - * This method returns something cool. {@link MyParentMethod} has other cool stuff in it. - * - * @param string $colour The colour of cool things that you want - * @return DataList A list of everything cool - */ - public function myMethod($foo) {} + /** + * My Method. + * This method returns something cool. {@link MyParentMethod} has other cool stuff in it. + * + * @param string $colour The colour of cool things that you want + * @return DataList A list of everything cool + */ + public function myMethod($foo) + { + // ... + } } -### Class Member Ordering +## Class Member Ordering Put code into the classes in the following order (where applicable). @@ -446,7 +132,7 @@ Put code into the classes in the following order (where applicable). * Template data-access methods (methods that will be called by a `$MethodName` or `<% loop $MethodName %>` construct in a template somewhere) * Object methods -### SQL Format +## SQL Format If you have to use raw SQL, make sure your code works across databases. Make sure you escape your queries like below, with the column or table name escaped with double quotes as below. @@ -464,15 +150,10 @@ are single quoted. Use [ANSI SQL](http://en.wikipedia.org/wiki/SQL#Standardization) format where possible. -### Secure Development +## Secure Development See [security](/developer_guides/security) for conventions related to handing security permissions. -## License - -Parts of these coding conventions were adapted from [Zend Framework](http://framework.zend.com/manual/en/coding-standard.overview.html), -which are licensed under BSD (see [license](http://framework.zend.com/license)). - ## Related * [JavaScript Coding Conventions](/contributing/javascript_coding_conventions)