Стандарти написання коду
Дата оновлення перекладу 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 і 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]
тощо.); - PДодавайте до 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 для всіх класів, методів та функцій (хоча вас можуть попросити видалити PHPDoc, який не додає цінності);
Використовуйте лише анотації та типи, визначені в довіднику PHPDoc. Для того, щоб покращити типи для статичної аналітики, також дозволяються наступні анотації:
- Дженерики, за виключенням
@template-covariant
. - Умовні зворотні типи, використовуючи
@psalm-return
з префіксом постачальника; - Константи класів;
- Типи викликаних;
- Дженерики, за виключенням
- Групуйте анотації разом, щоб анотації одного типу слідували одразу одна за одною, а анотації різних типів були розділені одним порожнім рядком;
- Опускайте тег
@return
, якщо метод нічого не повертає; - Не використовуйте блоки PHPDoc одного рядку в класах, методах та фцункціях, навіть коли
вони містять лише одну анотацію (наприклад, не розміщуйте
/** {@inheritdoc} */
в одному рядку); - При додоаванні нового класу або внесенні суттєвих змін у існуючий клас, може бути доданий або розширений
тег
@author
з особистими контактними даними. Будь ласка, відмітьте, що можливо оновлювати або видаляти особисту інфрмацію шяхом запиту до основної команди.
Ліцензія
- Symfony випускається під ліцензцію MIT, а блок ліцензції повинен бути присутній зверху кожного PHP-файлу перед простором імен.