Стандарти написання коду

Дата оновлення перекладу 2022-12-12

Стандарти написання коду

Код 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
93
94
95
/*
 * Цей файл є частиною пакету Symfony.
 *
 * (c) Фабієн Потенсьє <fabien@symfony.com>
 *
 * Для повної інформації про права власності та ліцензію, будь ласка перегляньте
 * файл LICENSE, який бул ррзповсюджено цим початковим кодом.
 */

namespace Acme;

use Other\Qux;

/**
 * Coding standards demonstration.
 */
class FooBar
{
    public const SOME_CONST = 42;

    /**
     * @var string
     */
    private $fooBar;
    private $qux;

    /**
     * @param $dummy some argument description
     */
    public function __construct(string $dummy, Qux $qux)
    {
        $this->fooBar = $this->transformText($dummy);
        $this->qux = $qux;
    }

    /**
     * @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)
    {
        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;
  • Не використовуйте 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] замість #[Command], але #[When] залишається як є);
  • Використовуйте 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. Для того, щоб покращити типи для статичної аналітики, також дозволяються наступні анотації:

  • Групуйте анотації разом, щоб анотації одного типу слідували одразу одна за одною, а анотації різних типів були розділені одним порожнім рядком;
  • Опускайте тег @return, якщо метод нічого не повертає;
  • Не використовуйте блоки PHPDoc одного рядку в класах, методах та фцункціях, навіть коли вони містять лише одну анотацію (наприклад, не розміщуйте /** {@inheritdoc} */ в одному рядку);
  • При додоаванні нового класу або внесенні суттєвих змін у існуючий клас, може бути доданий або розширений тег @author з особистими контактними даними. Будь ласка, відмітьте, що можливо оновлювати або видаляти особисту інфрмацію шяхом запиту до основної команди.

Ліцензія

  • Symfony випускається під ліцензцію MIT, а блок ліцензції повинен бути присутній зверху кожного PHP-файлу перед простором імен.