PSR + Experience = PHP code convention
Maksim N Epikhin (PIKHTA)
Posted on December 15, 2020
The following points were formed by analyzing the existing approaches of companies and personal experience.
File and folder naming rules
All names for folders and files should be meaningful and self-explanatory (not requiring additional clarification).
Folders
All folders are named in lowercase, word-delimited using the -
(minus) character.
If the folder contains classes that belong to the namespace, then the folder is named according to the name of the namespace.
Allowed characters for naming folders: Latin letters and the -
(minus) symbol.
Files
All files related to the project are named in lowercase word-delimited using the -
(minus) character.
If the file is a class file, it is named according to the class name.
Rules for naming namespaces, classes, methods and variables
All names should be meaningful and self-explanatory (not requiring additional clarification).
Namespaces
Namespace names must be in lowercase and consist of one word. If it is necessary to name namespaces for more than one word, it is split into constituent parts, which are nested namespaces.
Classes
Class names must match PascalCase
. In PascalCase
, each word starts with a capital letter.
Traits are postfixed with Trait
. Interfaces are postfixed with Interface
. Abstract classes are prefixed with Abstract
.
Methods
Method names must match camelCase
. camelCase
must start with a lowercase letter, and the first letter of each subsequent word must be capitalized. All words are written together
The following rules apply to method names:
- The name of the method should convey the intentions of the programmer
- The name of the method should tell why this method exists, that it
does and how it is used (
isPostRequest
,getRequestType
,parseSchemaElement
,renderPageWithSetupsAndTeardowns
) - The name of the method should not be short
- The name of the method must begin with a verb
- Names of
boolean
methods must contain the verbis
,has
orcan
Variables
Variable names must match camelCase
. camelCase
must start with a lowercase letter, and the first letter of each subsequent word must be capitalized. All words are written together
Constants must match UPPER_CASE_SNAKE_CASE
. In UPPER_CASE_SNAKE_CASE
, all words are written in capital letters, and spaces are replaced with underscores.
The following rules apply to variable names:
- The name of the variable should convey the intentions of the programmer
- The name of the variable should tell you why this variable exists, what it does and how it is used
- The name of the variable should not be short
- The name of the variable must not use the data type. The exception is
Map
($typesMap
,$statesMap
), because otherwise, it cannot be distinguished from an array with data. - If a variable stores a trait, then it must be included in the name (
unpaidProject
) - Variables reflecting the properties of the object must include the name of the object (
userIsAdmin
,messageIsSend
,figureCanBePainted
,projectName
) - Variables and properties of an object must be nouns and named so that they are read correctly when used, and not when initialized
Poorly:
$object->expire_at
$object->setExpireAt($date);
$object->getExpireAt();
Good:
$ object->expiration_date;
$ object->setExpirationDate($date);
$ object->getExpirationDate();
- Names of
boolean
variables must contain the verbis
,has
orcan
- Negative logical names are prohibited
Poorly:
if ($project->isInvalid()) {
// ...
}
if ($ project->isNotValid()) {
// ...
}
if ($accessManager->isAccessDenied()) {
// ...
}
Good:
if (!$project->isValid()) {
// ...
}
if (!$accessManager->isAccessAllowed()) {
// ...
}
if ($accessManager->canAccess()) {
// ...
}
- If there are properties (clause 8 and similar), the order of the variable name consists of: the name of the object in relation to which the variable is used), the property and the continuation of the variable name (
userHasRoleAdmin
,statusIsActive
)
Code design rules
First of all, the namespace is put, which is used (if any). Next, the constructs of using classes (use
) are written. In case of using several
Classes of the same namespace are grouped using the {...}
construction. Next comes the class declaration.
Curly braces appear on the same line and are separated by a space.
Round brackets:
- Inside are not separated by a space.
- Outside separated by spaces control structures
- There is no space after the method / function name.
Each variable must be declared on a new line.
Conditions and service calls of methods are separated by line breaks, variables and work with them by line breaks are not separated.
There is no additional line break inside conditions and loops.
The content of the class is delimited at the top by one blank line.
class InterfaceType {
private $property = 'myProp';
public function getProperty(): string {
return $ this-> property;
}
}
The return value (return
) must be preceded by a line break if the method does not consist of a single line.
If the condition is large, then be sure to select it in one or more semantic expressions and use it (them) in the condition.
Poorly:
if (IS_REGISTRATOR () && (($params.status === 'W' || $params.status === 'D' || $params.status === 'A') && $params.remark && ( ($params.subres_level == 0 && ($user_info->selected_title->tid == $params.boss || $user_info->selected_title->tid == $doc_signer_tid ||!$params.usertid) || $params.subres_level > 0 && $user_info->selected_title->tid == $params.usertid))) {...}
Good:
$docIsInWorkAcceptOrDraft = ...;
$bossHasSignerPriviledge = ...;
$userCanSign = ...;
if ($docIsInWorkAcceptOrDraft && $bossHasSignerPriviledge && $userCanSign) {
// ...
}
Code commenting
In general, comments are prohibited (NOT "always"). Any piece of code that needs to be highlighted or commented out should be placed in a separate method.
Comments should be placed before the declaration of classes, variables and methods and should be formatted in accordance with PHPDoc. The comment before the class should describe the business logic and reflect its purpose with examples of use.
Single-line comments are denoted by //
, and multi-line /*...*/
.
Finished algorithms taken from an external source must be marked with a link to the source.
Rules for writing code
Where it makes sense, declare (strict_types = 1);
Functions / methods use null
instead of missing scalar value. 0
and an empty string cannot be used as an indicator of a missing value.
function sendEmail(string $title, string $message = null, string $date = null): void {
// ...
}
// message was not sent
$object->sendEmail('Title', null, '2017-01-01');
// an empty message was sent
$object->sendEmail('Title', '', '2017-01-01');
You cannot change the variables that are passed to the method as input (exception - if this variable is an object).
You cannot assign the same value to several variables. To check if a key exists in an associative array, use array_key_exists
, not isset
. You cannot mix string and numeric keys in an array. Associative arrays cannot be sorted.
Lines are surrounded by single quotes. Double quotes are only used if:
- There must be single quotes inside the string
- Variable substitution is used inside the string
- Specials are used inside the line. characters
\n
,\r
,\t
, etc.
Instead of unnecessary concatenation, we use variable substitution in double quotes
Methods should use as much typing as possible, including the return type (: type
). All parameters and their types must be described in the method declaration or in PHPDoc. Name methods that start with check
and validate
should throw exceptions and not return values.
All class methods should be private
by default. If the method is used by the heirs of the class, then it is declared protected
. If used by third party classes then public
.
If the method can return null
, then it is desirable to implement the Null object design pattern, or throw an exception, or return a special case object (example: an empty array).
When returning from a data method of the json
type - it is unacceptable to writereturn true
, always use the construction return ['success' => ['message' => '.....']]
or ['error' => ['message' => '.....']]
. message
is given as an example, you can use any keys in an unlimited number.
The method must clearly distinguish between normal and exceptional situations.
By default, exception texts should not be shown to the user. They are meant for logging and debugging. The exception text can be shown to the user if it is explicitly intended to do so.
In a conditional statement, only the boolean
value must be checked. When comparing non-boolean
variables, strict comparison with type casting (===
) is used, automatic casting and loose comparison are not used.
Poorly:
if ($user) {
// ...
}
if ($request->postData('amount') == 100) {
// ...
}
if (!$request->postData('amount')) {
// ...
}
Good:
if ($user === null) {// $user is of type object
// ...
}
if ((int)$request->postData('amount') === 100) {
// ...
}
if ($booking->comment === '') {
// ...
}
When using the AND and OR operators in a conditional expression at the same time, be sure to prioritize parentheses.
Posted on December 15, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.