Стиль кодирования Yii 2 framework ================================= Описанный ниже стиль кодирования используется при разработке ядра Yii 2.x и его официальных расширений. Если вы хотите участвовать в разработке фреймворка, постарайтесь придерживаться данного стиля. Мы не принуждаем вас использовать этот стиль при разработке ваших приложений с использованием Yii 2. В данном случае можете использовать тот стиль, который вам больше подходит. Пример конфигурационного файла для CodeSniffer вы можете найти здесь: https://github.com/yiisoft/yii2-coding-standards ## 1. Обзор В общем, мы используем совместимый со стандартом [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) стиль, так что все положения [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) вполне применимы к нашему стилю кодирования. - ДОЛЖНЫ использоваться только открывающие теги `` или `` не нужен; - Не добавляйте лишние пробелы в конец строки; - Все файлы, содержащие PHP код, должны иметь расширение `.php`. ### 2.2. Кодировка символов PHP код должен содержать только символы в кодировке UTF-8 без BOM. ## 3. Имена Классов Имена классов ДОЛЖНЫ быть определены используя `StudlyCaps`. Например, `Controller`, `Model`. ## 4. Классы В данном случае, под классом подразумеваются все классы и интерфейсы. - При именовании классов следует использовать `CamelCase`; - Открывающая фигурная скобка всегда должна быть на следующей строке после имена класса; - Все классы должны быть документированы в соответствии с PHPDoc; - Весь код класса должен быть выровнен с использованием 4 пробелов; - В одном PHP файле должен быть только один класс; - Все классы должны использовать пространства имен; - Имя класса должно совпадать с именем файла. Пространство имен класса должно соответствовать структуре каталогов. ```php /** * Документация */ class MyClass extends \yii\base\BaseObject implements MyInterface { // код } ``` ### 4.1. Константы Константы класса ДОЛЖНЫ быть объявлены в верхнем регистре с подчеркиванием в качестве разделителей. Пример: ```php 'Yii', 'options' => ['usePHP' => true], ]; ``` ### 5.4 Управляющие конструкции - Оставляйте один пробел перед открывающей круглой скобкой и после закрывающей круглой скобки в управляющих конструкциях; - Операторы внутри круглых скобок должны разделяться пробелами; - Открывающая фигурная скобка должна быть на той же строке; - Закрывающая фигурная скобка должна быть на новой строке; - Всегда используйте фигурные скобки для однострочных выражений. ```php if ($event === null) { return new Event(); } if ($event instanceof CoolEvent) { return $event->instance(); } return null; // такой код недопустим: if (!$model && null === $event) throw new Exception('test'); ``` Старайтесь избегать использования `else` после `return` там, где это возможно. Используйте [граничные операторы](https://refactoring.guru/ru/replace-nested-conditional-with-guard-clauses). ```php $result = $this->getResult(); if (empty($result)) { return true; } else { // дальнейшие вычисления } ``` лучше переписать так: ```php $result = $this->getResult(); if (empty($result)) { return true; } // дальнейшие вычисления ``` #### switch Используйте следующий стиль для switch: ```php switch ($this->phpType) { case 'string': $a = (string) $value; break; case 'integer': case 'int': $a = (int) $value; break; case 'boolean': $a = (bool) $value; break; default: $a = null; } ``` ### 5.5 Вызовы функций ```php doIt(2, 3); doIt(['a' => 'b']); doIt('a', [ 'a' => 'b', 'c' => 'd', ]); ``` ### 5.6 Анонимные (lambda) функции Не забывайте про пробелы между ключевыми словами `function`/`use` и открывающими круглыми скобками: ```php // правильно $n = 100; $sum = array_reduce($numbers, function ($r, $x) use ($n) { $this->doMagic(); $r += $x * $n; return $r; }); // неправильно $n = 100; $mul = array_reduce($numbers, function($r, $x) use($n) { $this->doMagic(); $r *= $x * $n; return $r; }); ``` Документация ------------- - Для получения информации по синтаксису документации обратитесь к первоисточнику [PHPDoc](http://phpdoc.org/); - Код без документации недопустим; - Все файлы классов должны содержать блок документации в начале файла и блок документации непосредственно перед каждым классом; - Нет необходимости использовать тег `@return` если метод не возвращает значение; - Все виртуальные свойства классов, наследованных от `yii\base\BaseObject`, документируются тегом `@property` в блоке документации класса; Аннотации геттеров и сеттеров автоматически генерируются из соответствующих тегов `@return` or `@param` посредством выполнения команды `./build php-doc` в соответствующем каталоге; Вы можете добавить дополнительный тег `@property` для геттера или сеттера для пояснения назначения переменной метода, если это необходимо. Например: ```php * @since 2.0 */ class Component extends \yii\base\BaseObject ``` #### Функция / метод ```php /** * Returns the list of attached event handlers for an event. * You may manipulate the returned [[Vector]] object by adding or removing handlers. * For example, * * ``` * $component->getEventHandlers($eventName)->insertAt(0, $eventHandler); * ``` * * @param string $name the event name * @return Vector list of attached event handlers for the event * @throws Exception if the event is not defined */ public function getEventHandlers($name) { if (!isset($this->_e[$name])) { $this->_e[$name] = new Vector; } $this->ensureBehaviors(); return $this->_e[$name]; } ``` #### Разметка Как вы можете видеть в примерах выше, мы используем специальную разметку для форматирования комментариев PHPDoc. Ниже описан дополнительный синтаксис для описания связей между классами, методами и свойствами в документации: - `[[canSetProperty]]` создаст ссылку на метод или свойство `canSetProperty` этого класса; - `[[Component::canSetProperty]]` создаст ссылку на метод `canSetProperty` класса `Component` того же пространства имен; - `[[yii\base\Component::canSetProperty]]` создаст ссылку на метод `canSetProperty` класса `Component` в пространстве имен `yii\base`; - `[[Component]]` создаст ссылку на класс `Component` в том же пространстве имен. Здесь так же возможно явное указание пространства имен. Для явного указания текста ссылки возможно использование следующего синтаксиса: ``` ... as displayed in the [[header|header cell]]. ``` Часть до | это имя свойства, метода или класса для ссылки, а часто поле | это текст ссылки. Так же, возможно создание ссылок на Руководство: ```markdown [Руководство](guide:file-name.md) [Раздел руководства](guide:file-name.md#subsection) ``` #### Комментарии - Однострочные комментарии должны начинаться с `//`, а не с `#`; - Однострочные комментарии должны располагаться на отдельной строке. Дополнительные правила ---------------- ### `=== []` или `empty()` Используйте `empty()`, где это возможно. ### Несколько точек возврата Не допускайте запутанных вложенных условных конструкций, используйте return. Для коротких методов это не актуально. ### `self` или `static` Всегда используйте `static`, за исключением следующих случаев: - доступ к константам ДОЛЖЕН осуществляться через `self`: `self::MY_CONSTANT`; - доступ к защищенным статическим свойствам ДОЛЖЕН осуществляться через `self`: `self::$_events`; - допустимо использовать `self` для рекурсивного обращения к текущему классу, вместо класса наследника. ### Значение "ничего не делать" Свойства указывающее компоненту на отсутствие необходимости что-либо делать, должны принимать значение `false`. `Null`, `''`, или `[]` не должны использоваться в таких случаях. ### Каталоги/пространства имен - Используйте нижний регистр; - используйте множественное число для существительных, представляющих объекты (например валидаторы); - используйте единственное число для имен, представляющих соответствующий функционал (например web); - предпочтительнее использовать однословные пространства имён; - если одно слово использовать не удаётся, используйте camelCase стиль.