bit3 / php-coding-standard
bit3 PHP coding standards
Installs: 1 717
Dependents: 27
Suggesters: 0
Security: 0
Stars: 2
Watchers: 4
Forks: 0
Type:coding-standard
Requires
- phpmd/phpmd: ~1.4
- squizlabs/php_codesniffer: ~1.4
This package is not auto-updated.
Last update: 2022-02-01 12:26:15 UTC
README
These are our coding standards.
This coding standard based on the great TYPO3 coding standard, see http://forge.typo3.org/projects/team-php_codesniffer/wiki/Using_the_TYPO3_Coding_Standard
Philosophy
Our philosophy: Write fast readable and comprehensible code. Don't be shy to write more lines, if it makes each line more atomic.
What is the benefit of atomic lines? When each line is full atomic (only contains one operation), the order of lines reflect the execution order of the commands.
When you have a complex line like this:
$variable = ($foo != $bar && count($zap) || $dig) ? $this->func($zap, $foo, $bar) : $this->other(count($zap))->chain($foo, $bar);
How is the order of execution? What do this code? You can understand if you analyse the line, but its hard to do. Simplified this is the execution order of the operations:
evaluate $foo != $bar
execute count($zap)
evaluate count($zap)
evaluate .. && ..
evaluate $zip
evaluate .. || ..
if true
execute $this->func($zap, $foo, $bar)
else
execute count($zap)
evaluate count($zap)
execute $this->other(count($zap))
execute $..->chain($foo, $bar)
assign $variable
If you want to understand what this code do, you have to understand the execution order of the operations and the meaning of each operation. If you write this in a more atomic style, you make it easier to understand, for others and yourself if you nod touch the code a long time!
Compare against this, it is exactly the same code:
if ( $foo != $bar && count($zap) || $dig ) { $variable = $this->func($zap, $foo, $bar); } else { $variable = $this->other(count($zap))->chain($foo, $bar); }
As you can see, this snippet more reflect the execution order and it is much easier to understand what it do.
Usage
Install the coding standards via composer:
"require-dev":{ "bit3/php-coding-standard":"@dev" }
After updating dependencies, copy the example ant build file from vendor/bit3/php-coding-standard/example/build.xml into your project.
If your sources are not in src/
, change the path to your sources in the build file.
Hint: If you not use phpunit, remove the phpunit target from build file.
You can run the tests by invoke ant phpmd
and ant phpcs
.
Running ant
or ant test
will run all test targets.
Hint: To run all testes, even if one fail, use ant -keep-going
.
Definitions
- long line means a line that is longer than 60 characters.
- No line should be longer than 100 characters.
- No line must be longer than 120 characters.
Files
No file must contain more than one class, interface or function.
The file name must the same (including case) as the class, interface or function named defined in it.
Without any prefix (e.g. class.
) or suffix (e.g. .inc
), expect the the file type extension .php
.
Runner scripts, should contain a runner class, containing a run
method.
Example index.php
:
<?php require_once('autoload.php'); class index { public function run() { // runtime code } } $index = new index(); $index->run();
Hint: Runner classes must not be in pascal-case, but must match the file name.
Second example ajax.php
<?php class ajax { public function run() { // runtime code } } $ajax = new ajax(); $ajax->run();
Whitespaces
Do not use SPACE
for indention. Use TAB
.
Add spaces to split operators:
- assignment:
$variable = 'value'
- parameters:
func($a, $b, $c)
- arrays:
array('foo' => 'bar', 'bar' => 'foo')
- comments:
// comment
or* multiline comment
Class and function declaration
Place opening brace {
on new line for all non-control-structures like class or function declaration.
Place extends
and implements
on new line and indent one time.
class Foo extends Bar implements Zap { public function func() { ... } }
function func() { ... }
Don't add a space before opening bracked (
in function declarations or calls.
Naming
Use pascal-case class names.
// bad class foo_bar { } // good class FooBar { }
Use camel-case method names.
// bad function foo_bar() { } // good function fooBar() { }
Control structures
Place opening brace {
on same line for all control-structures.
Add newline after closing brace }
, even the control-structure continues.
if (...) { ... } else if (...) { ... } else { ... }
for (...) { ... }
foreach (...) { ... }
while (...) { ... }
do { ... } while (...);
Why putting the else
on a new line?
It's simple, first it is the beginning of a new block. Second it is easier to make comments that describe the conditions.
// describe if condition if (...) { ... } // describe else if condition else if (...) { ... } // describe else condition else { ... }
Long and multiline conditions
If control-structure condition gets to long, place closing bracket and opening brace ) {
in a separate line and place condition in separate line.
if ( ... very long ... ... multiline ... ) { ... } else if ( ... very long ... ... multiline ... ) { ... } else { ... }
for ( ... very long ... ... multiline ... ) { ... }
foreach ( ... very long ... ... multiline ... ) { ... }
while ( ... very long ... ... multiline ... ) { ... }
do { ... } while ( ... very long ... ... multiline ... );
Don't forget the whitespace before opening bracket (
.
Ternary operator
When using ternary operator, you should put then
and else
part in separate lines and indent one time if line gets longer.
// good $variable = $if ? $then : $else; // good $variable = $if ? $this->then() : $this->else(); // bad $variableObjectname = $someLongVariable != $otherLongVariable ? $veryLongVariableName : $anotherVeryLongVariableName; // good $variableObjectname = $someLongVariable != $otherLongVariable ? $veryLongVariableName : $anotherVeryLongVariableName;
Ternary operator should only be used for simple left/right decisions. Do not use in combination with complex conditions or logic.
// bad, use formated if-statement instead $variable = $firstVariable != $secondVariable && someCheckFunction($variableName) || anotherCheckFunction($thirdVariable) ? $this->someComplexFunction($firstVariable, $secondVariable, $thirdVariable) : 'some string prefix ' . substr($this->otherComplexFunction($variablename), 0, strlen($thirdVariable)) . ' some string suffix'; // good $variable = $firstVariable != $secondVariable ? $this->then() : $this->else(); // good $variable = someCheckFunction($variableName) ? $then : $else;
Function/Method calls
In function/method calls use space to split parameters, but do not add space before opening bracket (
.
// bad func ('a','b','c'); // good func('a', 'b', 'c');
When parameter list gets long, make it multiline and put every parameter on a singleline.
Also put the closing bracket )
on a singleline.
// bad func ('short', 'short', 'very long param'); // good func( 'short', 'short', 'very long param' );
When chain method calls, put each method call in separate line if it make sense or the line gets to long.
// bad
$database->prepare('SELECT a,long,list,of,fields FROM some_table WHERE some_complex_and_long_where')->limit(100)->offset(50)->execute();
// a little bit better
$database->prepare('SELECT a,long,list,of,fields FROM some_table WHERE some_complex_and_long_where')
->limit(100)->offset(50)->execute();
// good
$database
->prepare('SELECT a,long,list,of,fields FROM some_table WHERE some_complex_and_long_where')
->limit(100)
->offset(50)
->execute();
Variables
Initialisation
Make complex array initialisations multiline and put every element in single line.
$array = array( 'item1', 'item2', 'item3', );
$array = array( 'index1' => 'item1', 'index2' => 'item2', 'index3' => 'item3', );
Naming
Use camel-case variable names. Use significant variable names instead type prefix.
// bad $intUser = 1; // good $userId = 1;
// bad $objUser = ...some object...; // good $user = ...some object...;
// bad $arrUsers = array(1, 2, 3); // good $userIds = array(1, 2, 3);
// bad $arrUsers = array(...object..., ...object..., ...object...); // good $users = array(...object..., ...object..., ...object...);
Logic
Keep every line as simple as possible, do not combine to many operations in one line. Use readable control structures if needed, even you write a lot more lines!
// bad $variable = ($foo != $bar && count($zap) || $dig) ? $this->func($zap, $foo, $bar) : $this->other(count($zap))->chain($foo, $bar); // good $n = count($zap); if ( $foo != $bar && $n || $dig ) { $variable = $this->func($zap, $foo, $bar); } else { $variable = $this->other($n)->chain($foo, $bar); }
Don't use logic in function call parameters.
// bad func( $if ? $then : $else, 'foo', other('bar') ); // good $param = $if ? $then : $else; $other = other('bar'); func( $param, 'foo', $other );
Use function or method chaining with caution, but keep it as simple as possible.
// avoid illogical chaining // $this->func, strlen and file_get_contents does not logical belongs to each other $this->func(strlen(file_get_contents('/some/file'))); // better $content = file_get_contents('/some/file'); $this->func(strlen($content)); // best $content = file_get_contents('/some/file'); $length = strlen($content); $this->func($length);
// be gentle with logical chaining // the array_* functions are logical belongs to each other, // but its hard to understand this at a glance $result = array_values(array_filter(array_map('trim', $array))); // better $result = array_values( array_filter( array_map( 'trim', $array ) ) ); // best, keep it simple, fast readable and more comprehensible - and it is short :-) $result = array_map('trim', $array); $result = array_filter($result); $result = array_values($result);