
Стандарт PSR-12 на русском для PHP-разработчиков
Декабрь 11, 2019
Декабрь 11, 2019
PHP Standarts Recommendations — это рекомендации для PHP-разработчиков, разработанные PHP Framework Interop Group. Задача рекомендаций — помочь программистам унифицировать решения некоторых задач.
Redwerk.jobs первым сделал для вас перевод PSR-12. Соглашаться ли с рекомендациями — решать вам.
Ключевые слова «ДОЛЖНО», «НЕ ДОЛЖНО», «ТРЕБУЕТСЯ», «СЛЕДУЕТ», «НЕ СЛЕДУЕТ», «РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «НЕОБЯЗАТЕЛЬНЫЙ» в этом документе следует интерпретировать как описано в RFC 2119.
Эта спецификация расширяет и заменяет PSR-2, руководство по стилю кодирования, и требует соблюдения PSR-1, базового стандарта оформления кода.
Как и PSR-2, цель этой спецификации — упростить читаемость кода и убрать разногласия между разными авторами. Это достигается путем перечисления общего набора правил и ожиданий о том, как будет сформирован код PHP. Этот PSR предоставляет набор инструкций, которых могут придерживаться инструменты для форматирования, а разработчики могут легко установить связь между различными проектами. Когда различные авторы сотрудничают внутри одного проектами, это поможет иметь один набор руководящих принципов, который будет использоваться внутри проектов. Таким образом, преимущество этого руководства заключается не в самих правилах, а в совместном их использовании.
PSR-2 был принят в 2012 году, и с тех пор в PHP был внесен ряд изменений, которые повлияли на рекомендации по стилю кодирования. В то время как PSR-2 является довольно полным набором функционала PHP, который существовал на момент написания, новый функционал можно интерпретировать по-разному. Таким образом, этот PSR стремится прояснить содержание PSR-2 в более современном контексте, учитывая новые функциональные возможности.
В этом документе любые инструкции МОГУТ быть проигнорированы, если они не существуют в версиях PHP, поддерживаемых вашим проектом.
Этот пример охватывает некоторые из приведенных ниже правил в качестве краткого обзора:
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 |
<?php declare(strict_types=1); namespace Vendor \Package; use Vendor\Package\{ClassA as A, ClassB, ClassC as C}; use Vendor\Package\SomeNamespace\ClassD as D; use function Vendor\Package\{functionA, functionB, functionC}; use const Vendor\Package\{ConstantA, ConstantB, ConstantC}; class Foo extends Bar implements FooInterface { public function sampleFunction(int $a, int $b = null): array { if ($a === $b) { bar() } elseif ($a --> $b) { $foo->bar ($arg1); } else { BazClass::bar($arg2, $arg3); } } final public static function bar() { // method body } } |
Код ДОЛЖЕН соответствовать всем правилам, изложенным в PSR-1.
Термин «StudlyCaps» в PSR-1 ДОЛЖЕН интерпретироваться как PascalCase, где первая буква каждого слова пишется с большой буквы, включая самую первую букву.
Все файлы PHP ДОЛЖНЫ использовать только Unix LF (linefeed) в конец строки.
Все файлы PHP ДОЛЖНЫ заканчиваться непустой строкой, с одним LF в конце.
Закрывающий тег ?>
ДОЛЖЕН быть исключен в файлах, содержащих только PHP.
НЕ ДОЛЖНО быть жесткого ограничения (hard limit) на длину строки.
Мягкое ограничение (soft limit) на длину строки ДОЛЖНО быть 120 символов.
Строки НЕ ДОЛЖНЫ быть длиннее 80 символов; строки, длина которых превышает эту длину, ДОЛЖНЫ разбиваться на несколько последующих строк длиной не более 80 символов.
НЕ ДОЛЖНО быть пробелов в конце строк.
Пустые строки МОГУТ быть добавлены для улучшения читабельности и для обозначения связанных блоков кода, за исключением случаев, когда это запрещено.
НЕ ДОЛЖНО быть более одного оператора на строку.
Код ДОЛЖЕН использовать отступ в 4 пробела для каждого уровня отступа и НЕ ДОЛЖЕН использовать табуляцию для отступа.
Все ключевые слова и типы PHP [1] [2] ДОЛЖНЫ быть в нижнем регистре.
Любые новые виды и ключевые слова, добавленные в будущие версии PHP, ДОЛЖНЫ быть в нижнем регистре.
НЕОБХОДИМО использовать краткую форму ключевых слов, то есть bool
вместо boolean
, int
вместо integer
и т. д.
Заголовок файла PHP может состоять из нескольких различных блоков. Каждый следующий блок ДОЛЖЕН быть разделен одной пустой строкой и НЕ ДОЛЖЕН содержать пустую строку. Каждый блок ДОЛЖЕН быть в указанном ниже порядке, хотя нерелевантные блоки могут быть исключены.
<?php
.use
на основе классов.use
на основе функций.use
операторов import на основе констант.Если файл содержит HTML и PHP, любой из вышеперечисленных разделов все еще может использоваться. Если это так, они ДОЛЖНЫ присутствовать в верхней части файла, даже если остальная часть кода состоит из закрывающего тега PHP, а затем представляет собой смесь HTML и PHP.
Когда открывающий тег <?php
находится в первой строке файла, он ДОЛЖЕН находиться в отдельной строке без других операторов, если это не файл, содержащий разметку вне открывающих и закрывающих тегов PHP.
Операторы import НЕ ДОЛЖНЫ начинаться с обратной косой черты, поскольку они всегда должны быть полностью уточненный (qualified).
Следующий пример иллюстрирует полный список всех блоков:
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 |
<?php /** * This file contains an example of coding styles. */ declare(strict_types=1); namespace Vendor\Package; use Vendor\Package\{ClassA as A, ClassB, ClassC as C}; use Vendor\Package\SomeNamespace\ClassD as D; use Vendor\Package\AnotherNamespace\ClassE as E; use function Vendor\Package\{functionA, functionB, functionC}; use function Another\Vendor\functionD; use const Vendor\Package\{CONSTANT_A, CONSTANT_B, CONSTANT_C}; use const Another\Vendor\CONSTANT_D; /** * FooBar is an example class. */ class FooBar { // ... additional PHP code ... } |
Составные пространства имен с глубиной более двух НЕ ДОЛЖНЫ использоваться. Поэтому максимально допустимая глубина вложенности:
1 2 3 4 5 6 7 8 9 10 |
<?php use Vendor\Package\SomeNamespace\{ SubnamespaceOne\ClassA, SubnamespaceOne\ClassB, SubnamespaceTwo\ClassY, ClassZ, }; |
И не разрешено следующее:
1 2 3 4 5 6 7 8 9 |
<?php use Vendor\Package\SomeNamespace\{ SubnamespaceOne\AnotherNamespace\ClassA, SubnamespaceOne\ClassB, ClassZ, }; |
При желании объявить строгие типы в файлах, содержащих разметку вне открывающих и закрывающих тегов PHP, объявление ДОЛЖНО быть в первой строке файла и включать открывающий тег PHP, объявление строгих типов, и закрывающий тег.
Например:
1 2 3 4 5 6 7 8 9 10 |
<?php declare(strict_types=1) ?> <html> <body> <?php // ... additional PHP code ... ?> </body> </html> |
Операторы объявления НЕ ДОЛЖНЫ содержать пробелы и ДОЛЖНЫ быть такими: declare(strict_types=1)
(с необязательным ограничителем точки с запятой).
Операторы объявления блоков допускаются и ДОЛЖНЫ быть отформатированы, как показано ниже. Обратите внимание на положение фигурных скобок и интервалов:
1 2 3 4 5 |
declare(ticks=1) { // some code } |
Термин «класс» относится ко всем классам, интерфейсам, и признакам.
Любая закрывающая скобка НЕ ДОЛЖНА сопровождаться комментариями или утверждениями в той же строке.
При создании нового класса круглые скобки ДОЛЖНЫ присутствовать всегда, даже если в конструктор не переданы аргументы.
1 2 3 |
new Foo(); |
НЕОБХОДИМО, чтобы ключевые слова extends
и 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 { // constants, properties, methods } |
Списки implements
и, в случае интерфейсов, extends
МОГУТ быть разбиты на несколько строк, где каждая последующая строка имеет один отступ. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и ДОЛЖЕН быть только один интерфейс на строку.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable, \Serializable { // constants, properties, methods } |
Ключевое слово use
, используемое внутри классов для реализации признаков, ДОЛЖНО быть объявлено на следующей строке после открывающей скобки.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php namespace Vendor\Package; use Vendor\Package\FirstTrait; class ClassName { use FirstTrait; } |
Каждый отдельный трейт, который импортируется в класс, ДОЛЖЕН быть включен по одному на строку, и каждое включение ДОЛЖНО иметь свой собственный импорт оператор use
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php namespace Vendor\Package; use Vendor\Package\FirstTrait; use Vendor\Package\SecondTrait; use Vendor\Package\ThirdTrait; class ClassName { use FirstTrait; use SecondTrait; use ThirdTrait; } |
Когда у класса нет ничего после импорт оператора use
, закрывающая скобка класса ДОЛЖНА находиться на следующей строке после импорт оператора use
.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php namespace Vendor\Package; use Vendor\Package\FirstTrait; class ClassName { use FirstTrait; } |
В противном случае он ДОЛЖЕН иметь пустую строку после импорт оператора use
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php namespace Vendor\Package; use Vendor\Package\FirstTrait; class ClassName { use FirstTrait; private $property; } |
При использовании операторов insteadof
и as
они должны использоваться следующим образом, принимая во внимание отступы, интервалы, и новые строки.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php class Talker { use A, B, C { B::smallTalk insteadof A; A::bigTalk insteadof C; C::mediumTalk as FooBar; } } |
Видимость ДОЛЖНА быть объявлена на всех свойствах.
Видимость ДОЛЖНА быть объявлена для всех констант, если минимальная версия PHP вашего проекта поддерживает постоянные видимости (PHP 7.1 или более поздняя версия).
Ключевое слово var
НЕ ДОЛЖНО использоваться для объявления свойства.
НЕ ДОЛЖНО быть более одного свойства, объявленного на утверждение.
Имена свойств НЕ ДОЛЖНЫ иметь префикс с одним подчеркиванием для обозначения защищенной или приватной видимости. То есть префикс подчеркивания явно не имеет значения.
ДОЛЖЕН быть пробел между объявлением типа и именем свойства.
Объявление свойства выглядит следующим образом:
1 2 3 4 5 6 7 8 9 10 11 |
<?php namespace Vendor\Package; class ClassName { public $foo = null; public static int $bar = 0; } |
Видимость ДОЛЖНА быть объявлена во всех методах.
Имена методов НЕ ДОЛЖНЫ иметь префикс с одним подчеркиванием для обозначения защищенной или приватной видимости. То есть префикс подчеркивания явно не имеет значения.
Имена методов и функций НЕ ДОЛЖНЫ быть объявлены с пробелом после имени метода. Открывающая фигурная скобка ДОЛЖНА находиться на отдельной строке, а закрывающая фигурная скобка ДОЛЖНА находиться на следующей строке после тела. НЕ ДОЛЖНО быть пробела после открывающей скобки, и НЕ ДОЛЖНО быть пробела перед закрывающей скобкой.
Объявление метода выглядит следующим образом. Обратите внимание на расположение скобок, запятых, пробелов, и фигурных скобок:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace Vendor\Package; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } } |
Объявление функции выглядит следующим образом. Обратите внимание на расположение скобок, запятых, пробелов и фигурных скобок:
1 2 3 4 5 6 7 8 |
<?php function fooBarBaz($arg1, &$arg2, $arg3 = []) { // function body } |
В списке аргументов НЕ ДОЛЖНО быть пробела перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.
Аргументы метода и функции со значениями по умолчанию ДОЛЖНЫ помещаться в конец списка аргументов.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace Vendor\Package; class ClassName { public function foo(int $arg1, &$arg2, $arg3 = []) { // method body } } |
Списки аргументов МОГУТ быть разбиты на несколько строк, где каждая последующая строка имеет один отступ. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и в каждой строке ДОЛЖЕН быть только один аргумент.
Когда список аргументов разбит на несколько строк, закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть помещены вместе на отдельной строке с одним пробелом между ними.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php namespace Vendor\Package; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body } } |
Когда у вас есть объявление возвращаемого типа, ДОЛЖЕН быть один пробел после двоеточия, за которым следует объявление типа. Двоеточие и объявление ДОЛЖНЫ быть в одной строке с закрывающей скобкой списка аргументов без пробелов между двумя символами.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php declare(strict_types=1); namespace Vendor\Package; class ReturnTypeVariations { public function functionName(int $arg1, $arg2): string { return 'foo'; } public function anotherFunction( string $foo, string $bar, int $baz ): string { return 'foo'; } } |
В объявлениях типа Nullable НЕ ДОЛЖНО быть пробела между знаком вопроса и типом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php declare(strict_types=1); namespace Vendor\Package; class ReturnTypeVariations { public function functionName(?string $arg1, ?int &$arg2): ?string { return 'foo'; } } |
При использовании оператора ссылки &
перед аргументом, НЕ ДОЛЖНО быть пробела после него, как в предыдущем примере.
НЕ ДОЛЖНО быть пробела между оператором троеточия и именем аргумента:
1 2 3 4 5 6 |
public function process(string $algorithm, ...$parts) { // processing } |
При комбинировании оператора ссылки и оператора троеточия variadic, между ними не должно быть пространства:
1 2 3 4 5 6 |
public function process(string $algorithm, &...$parts) { // processing } |
Если они присутствуют, abstract
и final
объявления ДОЛЖНЫ предшествовать объявлению видимости.
Когда присутствует объявление static
, оно ДОЛЖНО быть после объявления видимости.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php namespace Vendor\Package; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } } |
При выполнении вызова метода или функции НЕ ДОЛЖНО быть пробела между именем метода или функции и открывающей скобкой. НЕ ДОЛЖНО быть пробела после открывающей скобки, и НЕ ДОЛЖНО быть пробела перед закрывающей скобкой. В списке аргументов НЕ ДОЛЖНО быть пробела перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.
1 2 3 4 5 6 7 |
<?php bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3); |
Списки аргументов МОГУТ быть разбиты на несколько строк, где каждая последующая строка имеет один отступ. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и в каждой строке ДОЛЖЕН быть только один аргумент. Один аргумент, разбитый на несколько строк (как это может быть в случае с анонимной функцией или массивом), не представляет собой разбиение списка аргументов.
1 2 3 4 5 6 7 8 9 |
<?php $foo->bar( $longArgument, $longerArgument, $muchLongerArgument ); |
1 2 3 4 5 6 7 8 9 10 11 |
<?php somefunction($foo, $bar, [ // ... ], $baz); $app->get('/hello/{name}', function ($name) use ($app) { return 'Hello ' . $app->escape($name); }); |
Общие правила стиля для контрольных структур следующие:
Тело каждой структуры ДОЛЖНО быть заключено в фигурные скобки. Это стандартизирует внешний вид структур и снижает вероятность появления ошибок при добавлении новых строк в тело.
Структура if
выглядит следующим образом. Обратите внимание на расположение скобок, пробелов и фигурных скобок; и что else
и elseif
находятся на той же строке, что и закрывающая скобка из предыдущего тела.
1 2 3 4 5 6 7 8 9 10 11 |
<?php if ($expr1) { // if body } elseif ($expr2) { // elseif body } else { // else body; } |
Ключевое слово elseif
ДОЛЖНО использоваться вместо else
, если все контрольные ключевые слова выглядят как отдельные слова.
Выражения в скобках МОГУТ разбиваться на несколько строк, где между каждой последующей строкой имеется минимум один отступ. При этом первое условие ДОЛЖНО быть на следующей строке. Закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть размещены вместе на отдельной строке с одним пробелом между ними. Логические операторы между условиями всегда ДОЛЖНЫ быть в начале или в конце строки, а не в обоих местах.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php if ( $expr1 && $expr2 ) { // if body } elseif ( $expr3 && $expr4 ) { // elseif body } |
Структура switch
выглядит следующим образом. Обратите внимание на расположение скобок, пробелов и фигурных скобок. Оператор case ДОЛЖЕН отделяться от switch
одним отступом, а ключевое слово break
(или другие завершающие ключевые слова) ДОЛЖНО иметь отступ на том же уровне, что и тело case. ДОЛЖЕН быть комментарий, такой как // no break
, когда fall-through является преднамеренным в непустом теле case
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?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; } |
Выражения в скобках МОГУТ разбиваться на несколько строк, где между каждой последующей строкой имеется минимум один отступ. При этом первое условие ДОЛЖНО быть на следующей строке. Закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть размещены вместе на отдельной строке с одним пробелом между ними. Логические операторы между условиями всегда ДОЛЖНЫ быть в начале или в конце строки, а не в обоих местах.
1 2 3 4 5 6 7 8 9 10 |
<?php switch ( $expr1 && $expr2 ) { // structure body } |
Оператор while
выглядит следующим образом. Обратите внимание на расположение скобок, пробелов, и фигурных скобок.
1 2 3 4 5 6 7 |
<?php while ($expr) { // structure body } |
Выражения в скобках МОГУТ разбиваться на несколько строк, где между каждой последующей строкой имеется минимум один отступ. При этом первое условие ДОЛЖНО быть на следующей строке. Закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть размещены вместе на отдельной строке с одним пробелом между ними. Логические операторы между условиями всегда ДОЛЖНЫ быть в начале или в конце строки, а не в обоих местах.
1 2 3 4 5 6 7 8 9 10 |
<?php while ( $expr1 && $expr2 ) { // structure body } |
Аналогично, оператор do while
выглядит следующим образом. Обратите внимание на расположение скобок, пробелов, и фигурных скобок.
1 2 3 4 5 6 7 |
<?php do { // structure body; } while ($expr); |
Выражения в скобках МОГУТ разбиваться на несколько строк, где между каждой последующей строкой имеется минимум один отступ. При этом первое условие ДОЛЖНО быть на следующей строке. Логические операторы между условиями всегда ДОЛЖНЫ быть в начале или в конце строки, а не в обоих местах.
1 2 3 4 5 6 7 8 9 10 |
<?php do { // structure body; } while ( $expr1 && $expr2 ); |
Формулировка for выглядит следующим образом. Обратите внимание на расположение скобок, пробелов, и фигурных скобок.
1 2 3 4 5 6 7 |
<?php for ($i = 0; $i < 10; $i++) { // for body } |
Выражения в скобках МОГУТ разбиваться на несколько строк, где между каждой последующей строкой имеется минимум один отступ. При этом первое условие ДОЛЖНО быть на следующей строке. Закрывающая скобка и открывающая фигурная скобка ДОЛЖНЫ быть размещены вместе на отдельной строке с одним пробелом между ними.
1 2 3 4 5 6 7 8 9 10 11 |
<?php for ( $i = 0; $i < 10; $i++ ) { // for body } |
Оператор foreach выглядит следующим образом. Обратите внимание на расположение скобок, пробелов, и фигурных скобок.
1 2 3 4 5 6 7 |
<?php foreach ($iterable as $key => $value) { // foreach body } |
Блок try-catch-finally
выглядит следующим образом. Обратите внимание на расположение скобок, пробелов, и фигурных скобок.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php try { // try body } catch (FirstThrowableType $e) { // catch body } catch (OtherThrowableType | AnotherThrowableType $e) { // catch body } finally { // finally body } |
Правила стилей для операторов сгруппированы по арности (количество операндов, которые они принимают).
Когда пространство разрешено вокруг оператора, МОЖНО использовать несколько пробелов для удобства чтения.
Все операторы, не описанные здесь, остаются неопределенными.
Операторы инкремента/декремента НЕ ДОЛЖНЫ иметь пробел между оператором и операндом.
1 2 3 4 |
$i++; ++$j; |
Операторы приведения типов НЕ ДОЛЖНЫ иметь пробела в скобках:
1 2 3 |
$intValue = (int) $input; |
Все бинарные арифметические, сравнительные, присваивающие, побитовые, логические, строковые, и типовые операторам ДОЛЖНЫ начинаться и заканчиваться пробелом:
1 2 3 4 5 6 7 |
if ($a === $b) { $foo = $bar ?? $a ?? $b; } elseif ($a > $b) { $foo = $a + $b * $c; } |
Условный оператору ДОЛЖЕН начинаться и заканчиваться пробелом вокруг обоих ?
и :
символов:
1 2 3 |
$variable = $foo ? 'foo' : 'bar'; |
Когда средний операнд условного оператора исключен, оператор ДОЛЖЕН следовать тем же правилам стиля, что и другие бинарные операторы сравнения:
$variable = $foo ?: ‘bar’;
Замыкания ДОЛЖНЫ быть объявлены с пробелом после ключевого слова function
и пробелом до и после ключевого слова use
.
Открывающая скобка ДОЛЖНА находиться на той же строке, а закрывающая скобка ДОЛЖНА переходить на следующую строку, следующую за телом.
НЕ ДОЛЖНО быть пробела после открывающей скобки списка аргументов или списка переменных, и НЕ ДОЛЖНО быть пробела перед закрывающей скобкой списка аргументов или списка переменных.
В списке аргументов и списке переменных НЕ ДОЛЖНО быть пробела перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.
Аргументы замыкания со значениями по умолчанию ДОЛЖНЫ помещаться в конец списка аргументов.
Если возвращаемый тип присутствует, он ДОЛЖЕН следовать тем же правилам, что и обычные функции и методы; если используется ключевое слово use
, двоеточие ДОЛЖНО следовать за закрывающими скобками списка использования без пробелов между двумя символами.
Объявление замыкания выглядит следующим образом. Обратите внимание на расположение скобок, запятых, пробелов, и фигурных скобок:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body }; $closureWithArgsVarsAndReturn = function ($arg1, $arg2) use ($var1, $var2): bool { // body }; |
Списки аргументов и списки переменных МОГУТ разбиваться на несколько строк, где каждая последующая строка имеет один отступ. При этом первый элемент в списке ДОЛЖЕН находиться на следующей строке, и в каждой строке ДОЛЖЕН быть только один аргумент или переменная.
Когда конечный список (будь то аргументы или переменные) разделен на несколько строк, закрывающая скобка и открывающая скобка ДОЛЖНЫ находиться на отдельной строке с одним пробелом между ними.
Ниже приведены примеры замыканий со списками аргументов и без них, а также списков переменных, разделенных на несколько строк.
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 45 46 47 |
<?php $longArgs_noVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) { // body }; $noArgs_longVars = function () use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_longVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_shortVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ($var1) { // body }; $shortArgs_longVars = function ($arg) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; |
Обратите внимание, что правила форматирования также применяются, когда замыкание используется непосредственно в вызове функции или метода в качестве аргумента.
1 2 3 4 5 6 7 8 9 10 11 |
<?php $foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 ); |
Анонимные классы ДОЛЖНЫ следовать тем же рекомендациям и принципам, что и закрытие в вышеприведенном разделе.
1 2 3 4 5 |
<?php $instance = new class {}; |
Открывающая фигурная скобка МОЖЕТ быть в той же строке, что и ключевое слово class, если список интерфейсов реализует ее. Если список implements переносится, фигурная скобка ДОЛЖНА быть помещена в строке, следующей непосредственно за последним интерфейсом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php // Brace on the same line $instance = new class extends \Foo implements \HandleableInterface { // Class content }; // Brace on the next line $instance = new class extends \Foo implements \ArrayAccess, \Countable, \Serializable { // Class content }; |