Стандарт PSR-2: Руководство по форматированию кода Павел Федорук, 03 ноября 2022 в 20:10

Стандарт PSR-2: Руководство по форматированию кода

Устарело - по состоянию на 10 августа 2019 г. PSR-2 помечен как устаревший.
В качестве альтернативы теперь рекомендуется PSR-12.

Это руководство дополняет и расширяет PSR-1, базовый стандарт разработки.

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

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

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

1. Обзор стандарта

  • Код ДОЛЖЕН следовать стандарту PSR-1.
  • Код ДОЛЖЕН использовать 4 пробела для отступа, а не табуляции.
  • НЕ ДОЛЖНО быть жестких ограничений на длину строки; мягкое ограничение ДОЛЖНО быть 120 символов; строки ДОЛЖНЫ быть 80 символов или меньше.
  • ДОЛЖНА быть одна пустая строка после объявления пространства имен и ДОЛЖНА быть одна пустая строка после объявлений блока использования.
  • Открывающие фигурные скобки для классов ДОЛЖНЫ идти на следующей строке, а закрывающие скобки ДОЛЖНЫ идти на следующей строке после тела.
  • Открывающие скобки для методов ДОЛЖНЫ идти на следующей строке, а закрывающие скобки ДОЛЖНЫ идти на следующей строке после тела.
  • Видимость ДОЛЖНА быть объявлена ​​для всех свойств и методов; abstract и final ДОЛЖНЫ быть объявлены до видимости; static ДОЛЖЕН быть объявлен после видимости.
  • Ключевые слова структуры управления ДОЛЖНЫ иметь один пробел после них; вызовы методов и функций НЕ ДОЛЖНЫ.
  • Открывающие фигурные скобки для управляющих структур ДОЛЖНЫ идти на той же строке, а закрывающие скобки ДОЛЖНЫ идти на следующей строке после тела.
  • Открывающие скобки для управляющих структур НЕ ДОЛЖНЫ иметь пробела после них, а закрывающие скобки для управляющих структур НЕ ДОЛЖНЫ иметь пробела перед ними.

1.1. Пример

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

<?php
namespace Vendor\Package;

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

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. Основное

2.1. Базовый стандарт

Вы должны следовать принципам стандарта PSR-1.

2.2. Файлы PHP

  • Все файлы PHP ДОЛЖНЫ использовать окончание строки Unix LF (перевод строки).
  • Все файлы PHP ДОЛЖНЫ заканчиваться одной пустой строкой.
  • Закрывающий тег ?> ДОЛЖЕН быть опущен в файлах, содержащих только PHP.

2.3. Строки

  • НЕ ДОЛЖНО быть жестких ограничений на длину строки.
  • Мягкое ограничение длины строки ДОЛЖНО составлять 120 символов; автоматические средства проверки стиля ДОЛЖНЫ предупреждать, но НЕ ДОЛЖНЫ выдавать ошибку при мягком лимите.
  • Строки НЕ ДОЛЖНЫ быть длиннее 80 символов; строки длиннее этого СЛЕДУЕТ разбивать на несколько последовательных строк не более 80 символов каждая.
  • НЕ ДОЛЖНЫ быть пробелы в конце непустых строк.
  • Пустые строки МОГУТ быть добавлены для улучшения читаемости и для обозначения связанных блоков кода.
  • НЕ ДОЛЖНО быть более одного оператора в строке.

2.4. Отступы

Код ДОЛЖЕН использовать отступ в 4 пробела и НЕ ДОЛЖЕН использовать табуляцию для отступа.

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

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

  • Ключевые слова PHP ДОЛЖНЫ быть в нижнем регистре.
  • Константы PHP true, false и null ДОЛЖНЫ быть в нижнем регистре.

3. Объявления пространства имен и use

  • При наличии ДОЛЖНА быть одна пустая строка после объявления пространства имен.
  • При наличии все объявления использования ДОЛЖНЫ идти после объявления пространства имен.
  • ДОЛЖНО быть одно ключевое слово use для каждого объявления.
  • После блока использования ДОЛЖНА быть одна пустая строка.

Например:

<?php
namespace Vendor\Package;

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

// далее PHP код

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

Термин «класс» относится ко всем классам, интерфейсам и трейтам.

4.1. Extends и Implements

  • Ключевые слова расширения и реализации ДОЛЖНЫ быть объявлены в той же строке, что и имя класса.
  • Открывающая фигурная скобка для класса ДОЛЖНА располагаться на отдельной строке; закрывающая фигурная скобка для класса ДОЛЖНА идти на следующей строке после тела.
<?php
namespace Vendor\Package;

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

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

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

<?php
namespace Vendor\Package;

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

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

4.2. Свойства

  • Видимость ДОЛЖНА быть объявлена для всех свойств.
  • Ключевое слово var НЕ ДОЛЖНО использоваться для объявления свойства.
  • В инструкции НЕ ДОЛЖНО быть объявлено более одного свойства.
  • Имена свойств НЕ ДОЛЖНЫ иметь префикс с одним подчеркиванием, чтобы указать защищенную или частную видимость.
  • Объявление свойства выглядит следующим образом.
<?php
namespace Vendor\Package;

class ClassName
{
    public $foo = null;
}

4.3. Методы

  • Видимость ДОЛЖНА быть объявлена для всех методов.
  • Имена методов НЕ ДОЛЖНЫ иметь префикс с одним подчеркиванием, чтобы указать защищенную или частную видимость.
  • Имена методов НЕ ДОЛЖНЫ объявляться с пробелом после имени метода. Открывающая фигурная скобка ДОЛЖНА располагаться на отдельной строке, а закрывающая скобка ДОЛЖНА располагаться на следующей строке после тела. НЕ ДОЛЖЕН быть пробел после открывающей скобки и НЕ ДОЛЖЕН быть пробел перед закрывающей скобкой.
  • Объявление метода выглядит следующим образом. Обратите внимание на размещение круглых скобок, запятых, пробелов и фигурных скобок:
<?php
namespace Vendor\Package;

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

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

  • В списке аргументов НЕ ДОЛЖЕН быть пробел перед каждой запятой и ДОЛЖЕН быть один пробел после каждой запятой.
  • Аргументы метода со значениями по умолчанию ДОЛЖНЫ идти в конец списка аргументов.
<?php
namespace Vendor\Package;

class ClassName
{
    public function foo($arg1, &$arg2, $arg3 = [])
    {
        // тело метода
    }
}
  • Списки аргументов МОГУТ быть разделены на несколько строк, где каждая последующая строка имеет один отступ. При этом первый элемент списка ДОЛЖЕН находиться на следующей строке, и в каждой строке ДОЛЖЕН быть только один аргумент.
  • Когда список аргументов разбит на несколько строк, закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть помещены вместе на отдельной строке с одним пробелом между ними.
<?php
namespace Vendor\Package;

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

4.5. abstract, final и static

  • При наличии объявления abstract и final ДОЛЖНЫ предшествовать объявлению видимости.
  • Если присутствует, static объявление ДОЛЖНО идти после объявления видимости.
<?php
namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

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

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

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

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

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

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

5. Структуры управления

Общие правила стиля для управляющих структур следующие:

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

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

5.1.  if, elseif, else

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

<?php
if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}

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

5.2. switch, case

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

<?php
switch ($expr) {
    case 0:
        echo 'Первый кейс с break';
        break;
    case 1:
        echo 'Второй случай, который продолжается ниже';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Третий случай, return вместо break';
        return;
    default:
        echo 'Default case';
        break;
}

5.3. do, while

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

<?php
while ($expr) {
    // тело цикла
}

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

<?php
do {
    // тело цикла;
} while ($expr);

5.4. for

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

<?php
for ($i = 0; $i < 10; $i++) {
    // тело цикла
}

5.5. foreach

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

<?php
foreach ($iterable as $key => $value) {
    // тело цикла
}

5.6. try, catch

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

<?php
try {
    // тело try
} catch (FirstExceptionType $e) {
    // тело исключения
} catch (OtherExceptionType $e) {
    // тело исключения
}

6. Замыкания

  • Замыкания ДОЛЖНЫ быть объявлены с пробелом после ключевого слова function и пробелом до и после ключевого слова use.
  • Открывающая фигурная скобка ДОЛЖНА располагаться на той же строке, а закрывающая скобка ДОЛЖНА располагаться на следующей строке после тела.
  • НЕ ДОЛЖНО быть пробела после открывающей скобки списка аргументов или списка переменных, и НЕ ДОЛЖНО быть пробела перед закрывающей скобкой списка аргументов или списка переменных.
  • В списке аргументов и списке переменных НЕ ДОЛЖЕН быть пробел перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.
  • Аргументы закрытия со значениями по умолчанию ДОЛЖНЫ идти в конец списка аргументов.
  • Объявление закрытия выглядит следующим образом. Обратите внимание на размещение круглых скобок, запятых, пробелов и фигурных скобок:
<?php
$closureWithArgs = function ($arg1, $arg2) {
    // тело функции
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // тело функции
};
  • Списки аргументов и списки переменных МОГУТ быть разделены на несколько строк, где каждая последующая строка имеет один отступ. При этом первый элемент в списке ДОЛЖЕН находиться на следующей строке, и в каждой строке ДОЛЖЕН быть только один аргумент или переменная.
  • Когда конечный список (будь то аргументы или переменные) разбит на несколько строк, закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть помещены вместе на отдельной строке с одним пробелом между ними.
  • Ниже приведены примеры замыканий со списками аргументов и без них, а также списков переменных, разбитых на несколько строк.
<?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
) {
    // тело функции
};

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

<?php
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // тело функции
    },
    $arg3
);

7. Выводы

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

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

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

Другие рецепты

Если вдруг, вы еще их не читали