New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PSR-1 Coding Style Guide (multi-chapter) #15
Changes from all commits
af71f89
69be98c
550dc72
0335b99
7bb84cd
49b6fef
c36244b
5aa80a2
3c5dea0
aecd965
93e6c5b
9cd5072
c6a7158
336336b
97003b0
c775d79
aac843f
d4b4c3d
fa5e0ba
ee14d0b
e977d3e
41c3ae5
e2bb63d
214b6a3
9412f14
cad7314
f51cce2
67af4d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,21 @@ | |||
Preamble | |||
======== | |||
|
|||
The goal for this guide is to increase consistency in style across disparate | |||
PHP projects written by multiple authors. It is intended to serve as a | |||
reference for reasonable expectations so as to reduce cognitive friction when | |||
scanning code from different projects. | |||
|
|||
This style guide is not a moral or ethical statement. It is an attempt to | |||
agree upon a common set of rules, requirements, recommendations, idioms, and | |||
approaches for code formatting. Any such guide is by nature arbitrary. The | |||
benefit is in the adherence to the rules, not in the rules themselves. | |||
|
|||
There are times when a particular rule or recommendation will not make sense | |||
in a particular limited context. Breaking the rule or recommendation in that | |||
particular limited context does not mean the remainder of the codebase under | |||
consideration is not PSR-1 compliant; instead, it is to be recognized as a | |||
regrettable but necessary departure from the guide for that one circumstance. | |||
|
|||
This guide is derived from commonalities between Horde, PEAR, Solar, Symfony, | |||
Zend, and other projects. | |||
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,9 @@ | |||
PHP Tags | |||
======== | |||
|
|||
Use the long `<?php ?>` tags for PHP code. Use of short-echo `<?= ?>` tags is | |||
also allowed. Do not use the other tag variations. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
Cf. <http://php.net/manual/en/language.basic-syntax.phpmode.php> | |||
|
|||
In files that contain only PHP, leave out the closing PHP tag. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,45 @@ | |||
Indenting and Line Length | |||
========================= | |||
|
|||
Indenting | |||
--------- | |||
|
|||
Use an indent of 4 spaces. Do not use tabs. The use of spaces helps to avoid | |||
problems with diffs, patches, history, and annotations, and provides | |||
fine-grained sub-indentation when aligning elements on consecutive lines. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
Line Length | |||
----------- | |||
|
|||
Lines should be limited to 75-85 characters in length. This is based on known | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not so sure this is good for code. This particular limit was popular when screen sizes were smaller, but now screens and resolutions are much bigger and 100 quite acceptable. This is something that is more appropriate for text files (like markdown or rst). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Horde, PEAR, Solar, Symfony, Zend, Lithium, et al. all note 80 characters as the expected line length (in some cases it's a soft limit, but it's still mentioned). Per comments elsewhere, screen size and resolution are not the driving factor; human cognitive limitations are. |
|||
human cognitive limitations, not the technical limitations of screen windows | |||
or text editors. When necessary, it is allowed to split a single statement | |||
across subsequent lines, per rules noted elsewhere in this guide. | |||
|
|||
Some further insight into the 75-85 characters rule: | |||
|
|||
> How many words per line can a person scan, and still be able to grasp the | |||
> content of the line in the context of the surrounding lines? Printing and | |||
> publishing typographers figured out a long time ago that most people can | |||
> read no more than 10 to 12 words per line before they have trouble | |||
> differentiating lines from each other. (A “word” is counted as five | |||
> characters on average.) Even allowing for a 25% to 50% increase, that | |||
> brings us up to 15 words. Times 5 characters per word, that means 75 | |||
> characters on a line. | |||
> | |||
> So the style guide limitation on line length is not exactly arbitrary. It | |||
> is about the developer’s ability to effectively scan and comprehend | |||
> strings of text, not about the technical considerations of terminals and | |||
> text-editors. | |||
|
|||
-- "Line Length, Volume, and Density" | |||
<http://paul-m-jones.com/archives/276> | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
|
|||
Other Considerations | |||
-------------------- | |||
|
|||
Code blocks may have as many blank lines as needed to increase readability | |||
and comprehension. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
Do not add trailing spaces at the end of lines. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,54 @@ | |||
`namespace`, `use`, and `class` | |||
=============================== | |||
|
|||
All namespaces and classes should be named with PSR-0 in mind. This means each | |||
class should be in a file by itself, and should be in a namespace of at least | |||
two levels: a top-level vendor name, and a second-level package name within | |||
that vendor. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not right. As far as I know the second level namespace is not enforced by PSR-0, and many many libs out there just have a vendor name namespace containing core classes. The key thing is that you don't have anything in the global namespace to avoid collisions & improve autoload-ability with prefixes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, you're right. All the examples have Vendor\Package, but the actual "Mandatory" bullet point only says "Vendor." Good catch! |
|||
|
|||
Class names are always in `StudlyCase`. The class declaration should have one | |||
empty line above it. The opening and closing braces for the class go on their | |||
own line. | |||
|
|||
<?php | |||
namespace Vendor\Package; | |||
|
|||
class ClassName | |||
{ | |||
// constants, properties, methods | |||
} | |||
|
|||
The `use` declarations go immediately after the namespace declaration with no | |||
line separating them. There should be one `use` keyword per declaration. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why shouldn't it be no lines separating them ? It may improve readability to regroup the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @clemherreman Others have argued, and I now agree, that namespace, use, and class should all have a line of separation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't say "should", but "may" :) |
|||
|
|||
<?php | |||
namespace Vendor\Package; | |||
use FooClass; | |||
use BarClass as Bar; | |||
use OtherVendor\OtherPackage\BazClass; | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Makes a lot of sense to me (for the same reasons I propose wrapping of method call parameters and array initialization with a trailing comma on the last line before a line followed with |
|||
|
|||
class ClassName | |||
{ | |||
// constants, properties, methods | |||
} | |||
|
|||
The `extends` and `implements` keywords should be on the same line as the | |||
class name. Lists of `implements` that exceed the line length limit may be | |||
split across multiple lines, where each subsequent line is indented once. | |||
List only one interface per line. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
<?php | |||
namespace Vendor\Package; | |||
use FooClass; | |||
use BarClass as Bar; | |||
use OtherVendor\OtherPackage\BazClass; | |||
|
|||
class ClassName extends ParentClass implements | |||
InterfaceName, | |||
AnotherInterfaceName, | |||
YetAnotherInterface, | |||
InterfaceInterface | |||
{ | |||
// constants, properties, methods | |||
} | |||
|
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,29 @@ | |||
Constants | |||
========= | |||
|
|||
The PHP keywords `true`, `false`, and `null` are all lower case all the time. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
All other user-defined constants are all upper case all the time, with | |||
underscore separators. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
<?php | |||
namespace Vendor\Package; | |||
|
|||
class ClassName | |||
{ | |||
const CONSTANT_NAME = 'constant value'; | |||
} | |||
|
|||
Global constants are strongly discouraged. Instead, create namespaced | |||
constants for the vendor and package: | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
<?php | |||
namespace Vendor\Package; | |||
const CONSTANT_NAME = 'constant_value'; | |||
|
|||
If a global constant is absolutely unavoidable, prefix it with the vendor and | |||
package name: | |||
|
|||
<?php | |||
define('VENDOR_PACKAGE_CONSTANT_NAME', 'constant_value'); | |||
|
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,32 @@ | |||
Variable And Property Names | |||
=========================== | |||
|
|||
This guide expressly avoids any requirement regarding the use of | |||
`$StudlyCase`, `$camelCase`, or `$under_score` variable and property names. It | |||
is often the case that variable names map directly field names in external | |||
data sources. Changing between naming conventions when changing contexts | |||
merely to suit a style guide would be counterproductive in such cases. | |||
|
|||
Some projects prefix property names with a single underscore to indicate a | |||
protected or private visibility. This guide discourages but does not disallow | |||
that practice. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
Whatever naming convention is used should be applied consistently within a | |||
reasonable scope. That scope may be vendor-level, package-level, class-level, | |||
or function-level. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
Class properties should explicitly note the visibility keyword. | |||
|
|||
<?php | |||
namespace Vendor\Package; | |||
|
|||
class ClassName | |||
{ | |||
public $property = null; | |||
} | |||
|
|||
Global variables are strongly discouraged. If a global variable is absolutely | |||
unavoidable, it should be prefixed with the vendor and package name. | |||
|
|||
<?php | |||
$Vendor_Package_VariableName = 'variable_value'; |
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,86 @@ | |||
Variable and Property Assignment | |||
================================ | |||
|
|||
Single Assignment | |||
----------------- | |||
|
|||
Assignment looks like the following. | |||
|
|||
$foo = 'value'; | |||
|
|||
To support readability, contiguous assignments may be aligned on the equals | |||
sign: | |||
|
|||
$short = fooBar($baz); | |||
$longer = dibGir($zim); | |||
|
|||
|
|||
Multi-Line Assignment | |||
--------------------- | |||
|
|||
Assignments may be split onto several lines when the line length limit is | |||
exceeded. The equals sign has to be positioned onto the following line, and | |||
indented once. | |||
|
|||
$this->longArrayPropertyName[$this->someOtherPropertyValue] | |||
= $object->getFunctionResult(ClassName::CONSTANT_VALUE); | |||
|
|||
Similarly, when concatenating strings across multiple lines, align the dot | |||
operator with the equals: | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✋ I'm not sure whether that's a great idea, Paul. I've done this in the past, too, and I liked it a lot, but when you start refactoring code it requires you to shift around a lot of lines, and if in bad luck, it's not done with a few
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What you suggest is what PEAR recommends, but ZF recommends aligning on the equals. After having used both, and after talking with others about it, we have found it easier when reading code to look down a single "column" of concatenation (i.e., when aligned on the equals). Does it cause editing troubles? Yes, but only when you change the length of the variable name. I think the tradeoff for aligning on equals is reasonable here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @pmjones, readability > writability. |
|||
|
|||
$foo = 'prefix string ' | |||
. $object->getSomeStringResult() | |||
. ' suffix string'; | |||
|
|||
$bar .= 'prefix string ' | |||
. $object->getSomeStringResult() | |||
. ' suffix string'; | |||
|
|||
|
|||
Ternary Assignment | |||
------------------ | |||
|
|||
Ternary assignments may be split onto subsequent lines when the exceed the | |||
line length limit, or when the would be more readable. Align the question mark | |||
and colon with the equals sign. | |||
|
|||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✋ See my comment. |
|||
$foo = ($expression1 && $expression2) | |||
? $foo | |||
: $bar; | |||
|
|||
$bar = ($expression3 && $expression4) | |||
? $a_very_long_variable_name | |||
: $bar; | |||
|
|||
|
|||
Assignment By Reference | |||
----------------------- | |||
|
|||
When assigning by reference, the `&` should be attached to the variable, not | |||
the operator: | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
// incorrect | |||
$foo =& $bar; | |||
|
|||
// correct | |||
$foo = &$bar; | |||
|
|||
|
|||
Array Assignment | |||
---------------- | |||
|
|||
Array assignments may be split across subsequent lines if they would otherwise | |||
break the line length limit, or if it would improve readability. They should be | |||
indented once per array, and should be aligned on the `=>` double arrow. The | |||
last value in each array should have a trailing comma; this is valid syntax | |||
and reduces the chance of syntax violations when adding new elements. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Trailing comma. ✋ Alignment with the |
|||
|
|||
$an_array = [ | |||
'foo' => 'bar', | |||
'subarray' => [ | |||
'baz' => 'dib', | |||
'zim' => 'gir', | |||
], | |||
'irk' => 'doom', | |||
]; | |||
|
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,90 @@ | |||
Function And Method Declarations | |||
================================ | |||
|
|||
Function and method names are in `camelCase`. | |||
|
|||
Some projects prefix function and method names with a single underscore to | |||
indicate a protected or private visibility. This guide discourages but does | |||
not disallow that practice. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
|
|||
Functions | |||
--------- | |||
|
|||
A function declaration looks like the following. Note the placement of | |||
parentheses, commas, spaces, and braces: | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
<?php | |||
namespace Vendor\Package; | |||
|
|||
function fooBarBaz($arg1, &$arg2, $arg3 = [], $arg4 = null) | |||
{ | |||
// function body | |||
} | |||
|
|||
This guide encourages using static class methods rather than functions; doing | |||
so helps to support autoloading. | |||
|
|||
Global functions are strongly discouraged. If a global function is | |||
unavoidable, prefix it with the vendor and package name. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 I believe that it's always avoidable, as it could be refactored into a static method of a |
|||
|
|||
<?php | |||
function Vendor_Package_FunctionName() | |||
{ | |||
// function body | |||
} | |||
|
|||
|
|||
Methods | |||
------- | |||
|
|||
Class methods are always be prefixed with an explicit visibility keyword: | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
<?php | |||
public function fooBarBaz($arg1, &$arg2, $arg3 = [], $arg4 = null) | |||
{ | |||
// function body | |||
} | |||
|
|||
Static methods always have the `static` keyword before the visibility keyword: | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✋ I've always felt visibility is of higher importance, therefore I suggest to have the On the other hand, it's not something I couldn't get used too. |
|||
|
|||
<?php | |||
static public function fooBarBaz($arg1, &$arg2, $arg3 = [], $arg4 = null) | |||
{ | |||
// function body | |||
} | |||
|
|||
|
|||
Arguments | |||
--------- | |||
|
|||
Arguments with default values always go at the end of the argument list. | |||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
|||
|
|||
Argument lists that exceed the line length limit may be split across | |||
subsequent indented lines. There is only one argument per line. The closing | |||
parenthesis and opening brace are placed together on their own line. | |||
|
|||
<?php | |||
static public function fooBarBaz( | |||
ClassTypeHint $arg1, | |||
&$arg2, | |||
array $arg3 = [], | |||
$arg4 = null | |||
) { | |||
// function body | |||
} | |||
|
|||
Anonymous Functions and Closures | |||
-------------------------------- | |||
|
|||
Declaration of anonymous functions looks like this; note the placement of | |||
parentheses, commas, spaces and braces: | |||
|
|||
$foo = function ($bar, $baz) use ($zim, $gir) { | |||
// body of the function | |||
}; | |||
|
|||
This is a departure from the "normal" function and method declaration. Because | |||
`function` is a keyword, it gets a space after it; the same is true for `use`. | |||
The opening brace goes on the same line as the declaration; the body is | |||
indented once; and the closing brace goes on its own outdented line. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use Zend Framework or ZF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call.