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

Код Symfony дополняется тысячами разработчиков со всего мира. Чтобы каждая часть кода выглядела и ощущалась знакомой, Symfony определяет некоторые стандарты написания кода, которым должны следовать все вкладчики.

Эти стандарты кода Symfony основаны на стандартах PSR-1, PSR-2 и PSR-4, так что вы уже можете знать большинство из них.

Как заставить ваш код следовать стандартам написания

Вместо того, чтобы вручную проверять ваш код, 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
 96
 97
 98
 99
100
101
102
103
<?php

/*
 * Этот файл является частью пакета Symfony.
 *
 * (c) Fabien Potencier <[email protected]>
 *
 * Чтобы получить полную информацию об авторском праве и лицензии, пожалуйста
 * просмотрите файл LICENSE, который поставляется с этим исходным кодом.
 */

namespace Acme;

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

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

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

    /**
     * @return string
     *
     * @deprecated
     */
    public function someDeprecatedMethod()
    {
        @trigger_error(sprintf('The %s() method is deprecated since version 2.8 and will be removed in 3.0. Use Acme\Baz::someMethod() instead.', __METHOD__), E_USER_DEPRECATED);

        return Baz::someMethod();
    }

    /**
     * Преобразует ввод, заданный в качестве первого аргумента.
     *
     * @param bool|string $dummy   Описание некоторого аргумента
     * @param array       $options Коллекция опций, которую нужно использовать при преобразовании
     *
     * @return string|null The transformed input
     *
     * @throws \RuntimeException When an invalid option is provided
     */
    private function transformText($dummy, array $options = array())
    {
        $defaultOptions = array(
            'some_default' => 'values',
            'another_default' => 'more values',
        );

        foreach ($options as $option) {
            if (!in_array($option, $defaultOptions)) {
                throw new \RuntimeException(sprintf('Unrecognized option "%s"', $option));
            }
        }

        $mergedOptions = array_merge(
            $defaultOptions,
            $options
        );

        if (true === $dummy) {
            return null;
        }

        if ('string' === $dummy) {
            if ('values' === $mergedOptions['some_default']) {
                return substr($dummy, 0, 5);
            }

            return ucwords($dummy);
        }
    }

    /**
     * Выполняет некоторую базовую проверку данного значения.
     *
     * @param mixed $value     Некоторое значение, которое нужно проверить
     * @param bool  $theSwitch Некоторый переключатель для контроля работы метода
     *
     * @return bool|void Резуультирующая проверка, если $theSwitch не false, иначе - void
     */
    private function reverseBoolean($value = null, $theSwitch = false)
    {
        if (!$theSwitch) {
            return;
        }

        return !$value;
    }
}

Структура

  • Добавляйте один пробел после каждой запятой-разграничителя;
  • Добавляйте один пробел вокруг бинарных операций(==, &&, ...), за исключением операции конкатенации (.);
  • Помещайте унарные операторы (!, --, ...) непосредственно с задействованной переменной;
  • Всегда используйте идентичное сравнение, кроме случаев, когда вам нужно жонглирование типами;
  • Испльзуйте условия Йоды при сопоставлении переменной с выражением, чтобы избежать случайного назначения внутри выражения условия (это применимо к ==, !=, ===, и !==);
  • Добавляйте запятую после каждого объекта массива в многстрочном массиве, даже после последнего;
  • Добавляйте пустую строку перед утверждениями return, кроме случаев, когда возврат осуществляется внутри группы утвеждений (как утверждение if);
  • Используйте return null;, когда функция ясно возвращает значения null и используйте return;, когда функция возвращает значения void;
  • Используйте скобки, чтобы обозначить тело структуры контроля независимо от количества содержащися в неё утверждений;
  • Определяйте один класс на файла - это не применимо к приватным классам помощников, которые не должны быть инстанциированы извне, и поэтому не рассматриваются автозагружаемыми стандартами PSR-0 and PSR-4;
  • Объявляйте наследуемость классов и все реализуемые интерфейсы в одной строке с именем класса;
  • Объявляйте свойства класса до методов;
  • Объявляйте вначале публичные методы, потом защищённые и потом - приватные. Исключением из этого правила являются конструктор класса и методы модульных PHP тестов setUp() и tearDown(), которые должны всегда быть первыми методами для большей удобочитаемости;
  • Объявляйте все аргументы в той же строке, что и имя метода или функции, независимо от того, сколько их;
  • Используйте круглые скобки при инстанциировании классов, независимо от количества аргументов в конструкторе;
  • Строки исключений и сообщений ошибок должны быть конкатенированы используя sprintf;
  • Вызовы trigger_error с типом E_USER_DEPRECATED должны быть переключены на согласие через оператор @. Прочтите больше в Deprecations;
  • Не используйте else, elseif, break после условий if и case, которые что-то вызывают или возвращают;
  • Не используйте пробелы вокруг относительного аксессора [ и перед относительным аксессором ].

Соглашения именования

  • Используйте camelCase, а не нижние подчёркивания, для имён переменных, функций, методов и аргументов;
  • Используйте нижние подчёркивания для опций конфигурации и параметров;
  • Используйте пространства имён для всех классов;
  • Добавляйте ко всем абстрактным классам, кроме PHPUnit *TestCase, префикс Abstract. Пожалуйста отметьте, что некоторые ранние классы Symfony не следуют этому соглашению и не были переименованы по причинам обратной совместимости. Однако, все новые абстрактные классы должны следовать этому соглашению именования;
  • Добавлйте к интерфейсам суффикс Interface;
  • Добавляйте к чертам суффикс Trait;
  • Добавляйте к исключениям суффикс Exception;
  • Используйте алфавитно-цифровые знаки и нижние подчёркивания для имён файлов;
  • Для типизирования в PHPDocs и приведениях, используйте bool (вместо boolean или Boolean), int (вместо integer), float (вместо double или real);
  • Не забывайте смотреть в более подробный документ Conventions для более субъективных правил именования.

Соглашения именования сервисов

  • Имя сервиса должно совпадать с полным именем класса (FQCN) его класса (например, App\EventSubscriber\UserSubscriber);
  • Если в одном классе существует несколько сервисов, используйте FQCN для главноо сервиса, а для остальных используйте имена в нижнем регистре и с нижними подчёркиваниями. По желанию можете разделить их на группы, разделённые точками (например, something.service_name, fos_user.something.service_name);
  • Используйте буквы нижнего регистра для имён параметров (кроме случаев ссылания на переменные окружения с синтаксисом %env(VARIABLE_NAME)%);
  • Добавьте дополнитедьные имена для публичных сервисов (например, дополнительное имя
Symfony\Component\Something\ClassName к something.service_name).

Документация

  • Добавляйте блоки PHPDoc для всех классов, методов и функций;
  • Группируйте аннотации вместе, чтобы аннотации одного типа следовали сразу же друг за другом, а аннотации разных типов были разделены одной пустой строкой;
  • Опускайте тег @return, если метод ничего не возвращает;
  • Аннотации @package и @subpackage не используются;
  • Не встраивайте блоки PHPDoc, даже если они содержат всего один тег (например, не помещайте /** {@inheritdoc} */ в одну строчку).

Лицензия

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

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.