Стандарты написания кода
Дата обновления перевода 2023-08-25
Стандарты написания кода
Код Symfony дополняется тысячами разработчиков со всего мира. Чтобы каждая часть кода выглядела и ощущалась знакомой, Symfony определяет некоторые стандарты написания кода, которым должны следовать все вкладчики.
Эти стандарты кода Symfony основаны на стандартах PSR-1, PSR-2,`PSR-4`_ и PSR-12, так что вы уже можете знать большинство из них.
Как заставить ваш код следовать стандартам написания
Вместо того, чтобы вручную проверять ваш код, Symfony делает так, чтобы проверка соответствия отправленного вами когда ожидаемому синтаксису кода была максимально лёгкой. Для начала, установите инструмент PHP CS Fixer, а потом выполните эту команду, чтобы исправить любую проблему:
1 2
$ cd your-project/
$ php php-cs-fixer.phar fix -v
Если вы забудете выполнить эту команду и сделаете запрос на включение с проблемой синтаксиса, наши автоматизированные инструменты предупредят вас об этом и предложат решение.
Стандарты написания кода Symfony в деталях
Если вы хотите узнать о стандартах написания кода Symfony в деталях, то вот краткий пример, содержащий большинство функций, описанных ниже:
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
/*
* Этот файл является частью пакета Symfony.
*
* (c) Фабьен Потенсье <fabien@symfony.com>
*
* Чтобы получить полную информацию об авторском праве и лицензии, пожалуйста
* просмотрите файл LICENSE, который поставляется с этим исходным кодом.
*/
namespace Acme;
use Other\Qux;
/**
* Демонстрация стандартов написания кода.
*/
class FooBar
{
public const SOME_CONST = 42;
private string $fooBar;
/**
* @param $dummy описание какого-то аргумента
*/
public function __construct(
string $dummy,
private Qux $qux,
) {
$this->fooBar = $this->transformText($dummy);
}
/**
* @deprecated
*/
public function someDeprecatedMethod(): string
{
trigger_deprecation('symfony/package-name', '5.1', 'The %s() method is deprecated, use Acme\Baz::someMethod() instead.', __METHOD__);
return Baz::someMethod();
}
/**
* Преобразует ввод, заданный в качестве первого аргумента.
*
* @param $options коллекция опций для использования в рамках преобразования
*
* @throws \RuntimeException Когда предоставлена невалидная опция
*/
private function transformText(bool|string $dummy, array $options = []): ?string
{
$defaultOptions = [
'some_default' => 'values',
'another_default' => 'more values',
];
foreach ($options as $name => $value) {
if (!array_key_exists($name, $defaultOptions)) {
throw new \RuntimeException(sprintf('Unrecognized option "%s"', $name));
}
}
$mergedOptions = array_merge($defaultOptions, $options);
if (true === $dummy) {
return 'something';
}
if (\is_string($dummy)) {
if ('values' === $mergedOptions['some_default']) {
return substr($dummy, 0, 5);
}
return ucwords($dummy);
}
return null;
}
/**
* Выполняет некоторые базовые операции для заданного значения.
*/
private function performOperations(mixed $value = null, bool $theSwitch = false): void
{
if (!$theSwitch) {
return;
}
$this->qux->doFoo($value);
$this->qux->doBar($value);
}
}
Структура
- Добавляйте один пробел после каждой запятой-разграничителя;
- Добавляйте один пробел вокруг бинарных операций(
==
,&&
, ...), за исключением операции конкатенации (.
); - Помещайте унарные операторы (
!
,--
, ...) непосредственно с задействованной переменной; - Всегда используйте идентичное сравнение, кроме случаев, когда вам нужно жонглирование типами;
- Используйте условия Йоды при сопоставлении переменной с выражением, чтобы
избежать случайного назначения внутри выражения условия (это применимо к
==
,!=
,===
, и!==
); - Добавляйте запятую после каждого объекта массива в многстрочном массиве, даже после последнего;
- Добавляйте пустую строку перед утверждениями
return
, кроме случаев, когда возврат осуществляется внутри группы утвеждений (как утверждениеif
); - Используйте
return null;
, когда функция ясно возвращает значенияnull
и используйтеreturn;
, когда функция возвращает значенияvoid
; - Не добавляйте возвратный тип
void
к методам в тестах; - Используйте скобки, чтобы обозначить тело структуры контроля независимо от количества содержащися в неё утверждений;
- Определяйте один класс на файла - это не применимо к приватным классам помощников, которые не должны быть инстанциированы извне, и поэтому не рассматриваются автозагружаемыми стандартами PSR-0 and PSR-4;
- Объявляйте наследуемость классов и все реализуемые интерфейсы в одной строке с именем класса;
- Объявляйте свойства класса до методов;
- Объявляйте сначала публичные методы, потом защищённые и потом - приватные.
Исключением из этого правила являются конструктор класса и методы модульных
PHP тестов
setUp()
иtearDown()
, которые должны всегда быть первыми методами для большей удобочитаемости; - Объявляйте все аргументы в той же строке, что и имя метода или функции, независимо от того, сколько их. Единственным исключением являются методы конструктора, использующие продвижение свойства конструктора, где каждый параметр должен быть на новой строке с замыкающей запятой;
- Используйте круглые скобки при инстанциировании классов, независимо от количества аргументов в конструкторе;
- Строки исключений и сообщений ошибок должны быть конкатенированы используя sprintf;
Сообщения об исключениях и ошибках не должны содержать обратных кавычек, даже при ссылке на технический элемент (например, имя метода или переменной). Двойные кавычки должны использоваться всегда:
1 2
- Ожидаемая опция `foo` будет одной из ... + Ожидаемая опция "foo" будет одной из ...
- Сообщения об исключениях и ошибках должны начинаться с заглавной буквы и заканчиваться
точкой
.
; Сообщения об исключениях, ошибках и устареваниях, содержащие имя класса, должны использовать
get_debug_type()
вместо::class
для их получения:1 2
- throw new \Exception(sprintf('Command "%s" failed.', $command::class)); + throw new \Exception(sprintf('Command "%s" failed.', get_debug_type($command)));
- Не используйте
else
,elseif
,break
после условийif
иcase
, которые что-то вызывают или возвращают; - Не используйте пробелы вокруг относительного аксессора
[
и перед относительным аксессором]
. - Добавляйте утверждение
use
к каждому классу, который не является частью глобального пространства имен; - Когда PHPDoc теги вроде
@param
или@return
включают в себяnull
и другие типы, всегда помещайтеnull
в конце списка типов.
Соглашения именования
- Используйте camelCase для переменных PHP, имен функций и методов, аргументов
(например,
$acceptableContentTypes
,hasSession()
); - Используйте snake_case для параметров конфигурации и переменных шаблонов Twig
(например,
framework.csrf_protection
,http_status_code
); - Используйте SCREAMING_SNAKE_CASE для констант (например,
InputArgument::IS_ARRAY
); - Используйте UpperCamelCase для случаев исчисления (например,
InputArgumentMode::IsArray
); - Используйте пространства имён для всех PHP-классов и UpperCamelCase для их имен
(например,
ConsoleLogger
); - Добавляйте ко всем абстрактным классам, кроме PHPUnit
*TestCase
, префиксAbstract
. Пожалуйста отметьте, что некоторые ранние классы Symfony не следуют этому соглашению и не были переименованы по причинам обратной совместимости. Однако, все новые абстрактные классы должны следовать этому соглашению именования; - Добавляйте к интерфейсам суффикс
Interface
; - Добавляйте к чертам суффикс
Trait
; - Не используйте посвящённый суффикс для классов или исчислений (например,
вроде
Class
илиEnum
), кроме случаев, описанных ниже. - Добавляйте к исключениям суффикс
Exception
; - Добавляйте к PHP-атрибутам префикс, связанный с конфигурацией сервиса с
As
(например,#[AsCommand]
,#[AsEventListener]
и т.д.); - Добавляйте к PHP-атрибутам префикс, связанный с аргументами контроллера с
Map
(например,#[MapEntity]
,#[MapCurrentUser]
и т.д.); - Используйте UpperCamelCase для именования PHP-файлов (например,
EnvVarProcessor.php
) и нижние подчеркивания для именования шаблонов Twig и веб-ресурсов (section_layout.html.twig
,index.scss
); - Для подсказок в PHPDocs и приведениях, используйте
bool
(вместоboolean
илиBoolean
),int
(вместоinteger
),float
(вместоdouble
илиreal
); - Не забывайте смотреть в более подробный документ Соглашения для более субъективных правил именования.
Соглашения именования сервисов
- Имя сервиса должно совпадать с полным именем класса (FQCN) его
класса (например,
App\EventSubscriber\UserSubscriber
); - Если в одном классе существует несколько сервисов, используйте FQCN для
главного сервиса, а для остальных используйте имена в нижнем регистре и с
нижними подчёркиваниями. По желанию можете разделить их на группы, разделённые
точками (например,
something.service_name
,fos_user.something.service_name
); - Используйте буквы нижнего регистра для имён параметров (кроме
случаев ссылания на переменные окружения с синтаксисом
%env(VARIABLE_NAME)%
); - Добавьте дополнитедьные имена для публичных сервисов (например, дополнительное имя
Symfony\Component\Something\ClassName
кsomething.service_name
).
Документация
- Добавляйте блоки PHPDoc для всех классов, методов и функций только когда они
добавляют релевантную информацию, которая не дублирует имя, заявление нативного
типа или контекст (напимер, проверки
instanceof
); Используйте только аннотации и типы, определённые в справочнике PHPDoc. Для того, чтобы улучшить типы для статичного анализа, следующие аннотации также разрешены:
- Дженерики, за исключением
@template-covariant
. - Условные типы возврата, используя
@psalm-return
с префиксом поставщика; - Константы класса;
- Типы вызываемых;
- Дженерики, за исключением
- Группируйте аннотации вместе, чтобы аннотации одного типа следовали сразу же друг за другом, а аннотации разных типов были разделены одной пустой строкой;
- Опускайте тег
@return
, если метод ничего не возвращает; - Не используйте блоки PHPDoc одной строки в классах, методах и функциях, даже если
они содержат только одну аннотацию (например, не размещайте
/** {@inheritdoc} */
в одной строке); - При добавлении нового класса, или внесении существенных изменений в существующий
класс, может быть добавлен или расширен тег
@author
с личными контактными данными. Пожалуйста, отметьте, что возможно обновлять или удалять личную информацию путем запроса к базовой команде.
Лицензия
- Symfony выпускается под лицензией MIT, и блок лицензии должен присутствовать сверху каждого PHP-файла, перед пространством имён.