Skip to content

Руководство по стилю кодирования

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

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

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

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

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

1. Обзор

  • Код ДОЛЖЕН следовать «руководству по стилю кодирования» PSR-1.

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

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

  • ДОЛЖНА быть одна пустая строка после объявления пространства имен (namespace), ДОЛЖНА быть одна пустая строка после блока объявлений use.

  • Открывающие скобки для классов ДОЛЖНЫ идти на следующей строке, а закрывающие скобки ДОЛЖНЫ перейти на следующую строку после тела класса.

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

  • Область видимости ДОЛЖНА быть объявлена для всех свойств и методов; ключевые слова 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 ДОЛЖНЫ использовать окончание строки Unix LF (перевод строки).

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

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

2.3. Строки

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

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

Строки НЕ ДОЛЖНЫ быть длиннее 80 символов; строки длиннее этого ДОЛЖНЫ быть разбит на несколько последовательных строк не более 80 символов каждая.

НЕ ДОЛЖНЫ быть пробелы в конце непустых строк.

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

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

2.4. Отступы

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

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

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

Ключевые слова (keywords) ДОЛЖНЫ быть в нижнем регистре.

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

3. Пространства имен и блоки импорта

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

При наличии все объявления use ДОЛЖНЫ идти после объявления namespace

В каждом объявлении ДОЛЖНО быть одно ключевое слово use.

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

Например:

<?php
namespace Vendor\Package;

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

// ... другой код ...

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

Здесь под «классом» следует понимать также интерфейсы (interface) и примеси (trait).

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
{
    // константы, свойства, методы
}

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

<?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 представлена ниже. Обратите внимание на расстановку скобок, пробелов и фигурных скобок и что else и elseif находятся на той же строке, что и закрывающая фигурная скобка из предыдущего тела конструкции.

<?php
if ($expr1) {
    // if блок
} elseif ($expr2) {
    // elseif блок
} else {
    // else блок;
}

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

5.2. Управляющие конструкции switch, case

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

<?php
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}

5.3. Управляющие конструкции while, 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
} catch (OtherExceptionType $e) {
    // блок catch
}

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. Заключение

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

  • Объявление глобальных переменных и глобальных констант

  • Объявление функций

  • Операторы и присваивание

  • Межстрочное выравнивание

  • Блоки комментариев и документации

  • Префиксы и суффиксы имени класса

  • Лучшие практики

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