PSR-2. Руководство по стилю кода.


Deprecated: Function create_function() is deprecated in /home/worldhel/public_html/wp-content/plugins/codecolorer/lib/geshi.php on line 4698

Данная статья, это авторский перевод, описания стандарта. С оригиналом описания Вы можете ознакомиться здесь

Данное руководство расширяет и дополняет рекомендации, указанные в PSR-1 (основной стандарт написания кода).

Цель данного руководства уменьшить мыслительную сложность восприятия, при изучении кода, написанного другими авторами. Эта цель достигается за счет установления общих правил и соглашений о стилевом форматировании PHP кода.

Данные правила были получены из общих черт проектов, написанных различными членами PHP-FIG. Когда различные авторы работают с различными проектами, то это помогает установить единый набор правил для использования во всех этих проектах. Таким образом, польза данного руководства, заключается не в установке самих правил, а в их максимально широком распространении и использовании.

Встречающиеся ключевые слова «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ТРЕБУЕТСЯ», «СЛЕДУЕТ», «НЕ СЛЕДУЕТ», «РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «ОПЦИОНАЛЬНО» в данном стандарте интерпретируются как описано в документе RFC 2119.

1. Общий обзор. 

  • Код ДОЛЖЕН следовать руководству по стилю кодирования PSR-1.
  • В коде ДОЛЖНЫ использоваться 4 пробела для отступа, но не знак табуляции.
  • НЕ ДОЛЖНО быть жесткого ограничения длины строки, при этом СЛЕДУЕТ стремиться соблюдать длину строки не более 80 символов, в нужных случаях рекомендуемым лимитом является длина не более 120 символов.
  • ДОЛЖНА быть одна пустая строка после объявления пространства имен, ключевое слово namespace, также ДОЛЖНА быть одна пустая строка после блока импорта/создания псевдонима имени с помощью оператора use.
  • Открывающая скобка для тела класса { ДОЛЖНА располагаться на следующей строке после объявления класса, а закрывающая скобка } ДОЛЖНА находиться на следующей строке после тела класса.
  • Открывающая скобка { для методов ДОЛЖНА располагаться на следующей строке после объявления функции, а закрывающая скобка } должна находиться на следующей строке после тела метода.
  • Область видимости, задаваемая ключевыми словами public, protected, private, ДОЛЖНА быть обязательно указана для всех  свойств и методов. Ключевые слова abstract и final ДОЛЖНЫ быть объявлены перед объявлением области видимости. Ключевое слово static  также ДОЛЖНО располагаться после объявления области видимости.
  • После ключевых слов в управляющих конструкциях (if, while, for и т.д.) обязательно ДОЛЖЕН быть один символ пробела, а вот после вызова метода или вызова функции пробела быть НЕ ДОЛЖНО.
  • Для управляющих конструкций открывающая скобка { ДОЛЖНА располагаться в той же строке, а вот закрывающая скобка } ДОЛЖНА идти на следующей строке после тела управляющей конструкции.
  • Открывающая круглая скобка ( в управляющих конструкциях НЕ ДОЛЖНА иметь символ пробела после себя, и также символа пробела НЕ ДОЛЖНО быть перед закрывающей круглой скобкой ).

1.1. Пример.

Пример кода ниже включает в себя некоторые из описанных в данном стандарте требования, и служит для быстрого наглядного примера:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazzClass;

class Foo extends Bar implements FooInterface
{
    public function sampleMethod($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2 $arg3);
        }
    }

    final public static function bar()
    {
         // тело метода
    }
}

 

2. Общие рекомендации. 

Основной стандарт стиля кода.

Код ДОЛЖЕН следовать всем правилам описанным в стандарте PSR-1

2.2. Файлы.

Все PHP файлы ДОЛЖНЫ использовать в конце строки символ переноса строки Unix LF (linefeed).

Все PHP файлы ДОЛЖНЫ оканчиваться одной пустой строкой.

Если файл содержит только PHP код, то в конце НЕ ДОЛЖНО быть закрывающего тега ?>.

2.3. Строки.

НЕ ДОЛЖНО быть строгого ограничения на длину строки.

Допустимый предел длины строки ДОЛЖЕН быть не более 120 символов. Автоматические системы проверки стиля кода ДОЛЖНЫ предупреждать об этом, но НЕ ДОЛЖНЫ выдавать ошибку при таком мягком ограничении.

Строки НЕ ДОЛЖНЫ быть длиннее, чем 80 символов. Если длина строки больше, то СЛЕДУЕТ ее разделить на несколько следующих друг за другом строк таким образом, чтобы длина каждой не превышала 80 символов.

Непустые строки НЕ ДОЛЖНЫ завершаться символами пробелов.

Пустые строки МОГУТ быть добавлены для улучшения читабельности кода, а также для визуального указания логически связанных участков кода.

НЕ ДОЛЖНО быть более одного оператора в строке.

2.4. Отступы.

В коде для отступов ДОЛЖНЫ использовать 4 символа пробела,
но НЕ ДОЛЖЕН применяться символ табуляции.

Обратите внимание: Использование только символов пробела, а не смешивания пробелов с символами табуляции, помогает избежать проблем при работе историей изменения кода, с аннотациями и с патчами. Также использование только символов пробелов, делает проще вставку небольших полу-отступов для выравнивания строк кода.

2.5. Ключевые слова True/False/Null.

Ключевые слова ЯП PHP ДОЛЖНЫ использоваться в нижнем регистре.

Константы ЯП PHP: true, false и null ДОЛЖНЫ использоваться в нижнем регистре.

3. Пространства имен и блока с use (импорт/объявление псевдонимов).

Если имеется блок объявления пространства имен namespace, то после него обязательно ДОЛЖНА быть одна пустая строка.

Если в коде используется блок импорта/создания псевдонима имени с помощью use, то такой блок ДОЛЖЕН располагаться после объявления пространства имен namespace.

Для каждого блока импорта/создания псевдонима ДОЛЖНО каждый раз быть использовано одно ключевое слово use.

После всего блока use ДОЛЖНА располагаться одна пустая строка.

Для примера:

1
2
3
4
5
6
7
8
<?php
namespace Vendor\Package;

use FooClass;
use BarCladd as Bar;
use OtherVendor\OtherPackage\BazClass;

// ....продолжение кода....

4. Классы, Свойства и Методы.

Под термином «класс» здесь подразумеваются все классы, интерфейсы и трейты.

4.1. Ключевые слова Extends и Implements.

Ключевые слова extends и implements ДОЛЖНЫ располагаться в той же строке, что и имя класса.

Открывающая скобка для тела класса { ДОЛЖНА располагаться на следующей строке после объявления класса, а закрывающая скобка } ДОЛЖНА находиться на следующей строке после тела класса.

1
2
3
4
5
6
7
8
9
10
11
<?php
namespace Vendor\Package;

use FooClass;
use BarCladd as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // Константы, свойства, методы...
}

Списки реализуемых интерфейсов после ключевого слова implements МОГУТ быть разделены на несколько строк, где каждые последующие строки имеют одинаковые отступы. При этом первый элемент списка ДОЛЖЕН быть на новой строке, и каждый последующий интерфейс списка ДОЛЖЕН быть на отдельной строке.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // Константы, свойства, методы
}

4.2. Свойства.

Область видимости, задаваемая при помощи ключевых слов private, public, protected, ДОЛЖНА быть указана для всех свойств класса.

Ключевое слово var НЕ ДОЛЖНО использоваться при объявлении свойства.

В одном выражении НЕ ДОЛЖНО быть более одного свойства.

В целях визуального указания области видимости свойства, которое является защищенным (protected) или приватным (pivate), в имени свойства НЕ СЛЕДУЕТ использовать префикс в виде одного символа подчеркивания.

При объявлении свойств класса, придерживайтесь ниже следующего кода:

1
2
3
4
5
6
7
<?php
namespace Vendor\Package;

class ClassName
{
    public $foo = null;
}

4.3. Методы.

Область видимости ДОЛЖНА указываться при объявлении всех методов.

Для указания, что метод имеет область видимости proetcted или private, НЕ СЛЕДУЕТ в имени метода использовать префикс в виде одного символа подчеркивания.

При объявлении метода, после имени метода НЕ ДОЛЖНЫ иметься символы пробелов. После имени метода сразу располагается круглая открывающая скобка, при этом НЕ ДОЛЖНО быть символов пробела после открывающий круглой скобки, и НЕ ДОЛЖНО быть символов пробела перед закрывающей круглой скобкой. Также открывающая скобка для тела класса { ДОЛЖНА располагаться на следующей строке после объявления класса, а закрывающая скобка } ДОЛЖНА находиться на следующей строке после тела класса.

При объявлении метода класса, придерживайтесь ниже следующего кода. При этом обратите внимание на размещение круглых скобок, запятых, пробелов и фигурных скобок:

1
2
3
4
5
6
7
8
9
10
<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 =[])
    {
        // тело метода
    }
}

4.4. Аргументы методов.

В списке аргументов метода НЕ ДОЛЖНО быть символа пробела перед запятой, но при этом ДОЛЖЕН быть символ пробела после каждой запятой.

Аргументы метода у которых имеются значения по умолчанию ДОЛЖНЫ идти в конце списка аргументов.

1
2
3
4
5
6
7
8
9
10
<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 =[])
    {
        // тело метода
    }
}

Список аргументов МОЖНО разделить на несколько строк, таким образом, чтобы каждые последующие строки имели одинаковый отступ. При этом первый аргумент списка ДОЛЖЕН располагаться на новой строке, и каждый последующий аргумент также ДОЛЖЕН находиться на новой отдельной строке.

Когда список аргументов разбивается на несколько строк, то закрывающая круглая скобка ) и открывающая фигурная скобка { ДОЛЖНЫ быть размещены вместе на одной отдельной строке с одним пробелом между ними.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // тело метода
    }
}

4.5. Ключевые слова abstract, final и static.

Когда используются ключевые слова abstract и final, то они должны располагаться перед объявлением области видимости (public, protected, private).

Когда используется ключевое слово static, то оно ДОЛЖНО располагаться после объявления области видимости.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // тело метода
    }
}

4.6. Вызовы функций и методов.

Когда производится вызов функции или метода, то НЕ ДОЛЖНО быть символа пробела между именем функции или метода и открывающей круглой скобкой, НЕ ДОЛЖНО быть пробела и после открывающей круглой скобки, также НЕ ДОЛЖНО быть символа пробела перед закрывающей круглой скобкой. В списке аргументов НЕ ДОЛЖНО быть символа пробела перед символами запятой, но при этом обязательно ДОЛЖЕН быть пробел после каждой запятой.

1
2
3
4
<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

Список аргументов МОЖНО разделить на несколько строк, таким образом, чтобы каждые последующие строки имели одинаковый отступ. При этом каждый аргумент списка ДОЛЖЕН располагаться на новой отдельной строке

1
2
3
4
5
6
<?php
$foo->bar(
    $longArgment,
    $longerArgument,
    $muchLongerArgument
);

5. Управляющие конструкции.

Общие требования к стилю управляющих конструкций:

  • ДОЛЖЕН быть один символ пробела после ключевого слова управляющей конструкции.
  • НЕ ДОЛЖНО быть символа пробела после открывающей круглой скобки.
  • НЕ ДОЛЖНО быть символа пробела перед закрывающей круглой скобкой.
  • ДОЛЖЕН быть один пробел между закрывающей круглой и открывающей фигурной скобками.
  • Код в теле управляющей конструкции ДОЛЖЕН иметь один отступ.
  • Закрывающая фигурная скобка } должна располагаться на следующей строке после тела управляющей конструкции.

Также тело каждой управляющей конструкции ДОЛЖНО быть заключено в фигурные скобки. Это стандартизирует, как выглядят управляющие конструкции, и уменьшает вероятность возникновения ошибок по мере добавления новых строк в тело конструкций.

5.1. if, elseif и else.

Конструкция if выглядит как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок, а также, что else и elseif находятся на той же линии, что и заключительная фигурная скобка из предыдущего тела управляющей конструкции.

1
2
3
4
5
6
7
8
<?php
if ($expr1) {
    // тело if
} elseif ($expr2) {
    // тело elseif
} else {
    // тело else
}

Ключевое слово elseif СЛЕДУЕТ использовать вместо раздельного else if, таким образом все ключевые слова управляющей конструкции будут выглядеть в одно слово.

5.2. switch, case.

Конструкция switch выглядит, как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок. Ключевое слово case ДОЛЖНО иметь один отступ по сравнению с case[/case], а ключевое слово [cci]break (или другое ключевое слово, имеющее эффект выхода из управляющей конструкции) ДОЛЖНО располагаться с тем же отступом, что и другие строки внутри case. Также, когда намеренно не используется выход из непустого case управляющей конструкции, то для таких ситуаций ДОЛЖЕН быть использован комментарий // no break.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
switch ($expr) {
    case 0:
        echo 'Первый case, с применением break';
        break;
    case 1:
        echo 'Второй case, после которого выполнением кода будет продолжено';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Третий case, с использованием return вместо break';
        return;
    default:
        echo 'Код по умолчанию для всех остальных случаев';
        break;
}

5.3. while, do while.

Конструкция while выглядит как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

1
2
3
4
<?php
while ($expr) {
    // тело управляющей конструкции
}

Аналогично, конструкция do while выглядит как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

1
2
3
4
<?php
do {
    // тело управляющей конструкции
} while ($expr);

5.5. foreach.

Конструкция foreach выглядит как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

1
2
3
4
<?php
foreach ($iterable as $key => $value) {
    // тело управляющей конструкции
}

5.6. try, catch.

Блок try catch выглядит как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

1
2
3
4
5
6
7
8
<?php
try {
    // тело блока try
} catch (FirstExceptionType $e) {
    // тело блока catch
} catch (OtherExceptionType $e) {
    // тело блока catch
}

6. Замыкания.

Замыкания ДОЛЖНЫ объявляться с использованием символа пробела после ключевого слова function, и символами пробелов до и после ключевого слова use.

Открывающая фигурная скобка ДОЛЖНА располагаться на той же строке, а закрывающая фигурная скобка ДОЛЖНА располагаться на следующей строке после тела функции.

НЕ ДОЛЖНО быть символа пробела после открывающей круглой скобки для списка аргументов или списка переменных, а также НЕ ДОЛЖНО быть пробелов перед закрывающей круглой скобкой списка аргументов или списка переменных.

В списке аргументов и списке переменных НЕ ДОЛЖЕН быть символ пробела перед каждой запятой, но ДОЛЖЕН быть один символ пробела после каждой запятой.

Замыкаемые аргументы, имеющие значения по умолчанию ДОЛЖНЫ располагаться в конце списка аргументов.

Объявление замыкания выглядит как в примере кода ниже. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок:

1
2
3
4
5
6
7
8
<?php
$closureWithArgs = function ($arg1, $arg2) {
    // тело функции
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // тело функции
};

Список аргументов и переменных МОЖНО разделить на несколько строк, таким образом, чтобы каждые последующие строки имели одинаковый отступ. При этом каждый аргумент списка ДОЛЖЕН располагаться на новой отдельной строке

Когда оканчивается список аргументов или переменных, разбитый на несколько строк, то закрывающая круглая скобка и открывающая фигурная скобка ДОЛЖНЫ быть размещены вместе на одной строке с одним пробелом между ними.

В коде ниже приведены примеры замыканий и со списком аргументов и со списком переменных, которые располагаются на разных строках.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
    // тело функции
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // тело функции
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // тело функции
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
    // тело функции
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // тело функции
};

Обратите внимание, что правила форматирования также применяются, когда замыкание используется непосредственно в вызове функции или метода в качестве аргумента.

1
2
3
4
5
6
7
8
<?php
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // тело функции
    },
    $arg3
);

7. Заключение.

Существует много элементов стиля и практики, преднамеренно не освещенных в этой рекомендации. К ним относятся, но не ограничиваются:

  • Объявление глобальных переменных и глобальных констант.
  • Объявление функций.
  • Операторы и присваивание.
  • Межстрочное выравнивание.
  • Блоки комментариев и документации.
  • Префиксы и суффиксы в именах классов.
  • Применение лучших практик.

Будущие рекомендации МОГУТ пересматривать и расширять это руководство для рассмотрения различных элементов стиля и хорошей практики.