Yii2: Современный стиль PHP кода

 

Keep calm and follow PHP PSR

При разработке приложений на Yii 2 полезно придерживаться стиля кода его разработчиков. Если, конечно, у вас нет своего устоявшегося стиля, соответствующего современному PHP и PSR.

Стиль кодирования Yii2 framework

Описанный ниже стиль кодирования используется при разработке ядра Yii 2.x и его официальных расширений. Если вы хотите участвовать в разработке фреймворка, постарайтесь придерживаться данного стиля. Мы не принуждаем вас использовать этот стиль при разработке ваших приложений с использованием Yii 2. В данном случае можете использовать тот стиль, который вам больше подходит.

Пример конфигурационного файла для CodeSniffer вы можете найти здесь: https://github.com/yiisoft/yii2-coding-standards.

1. Обзор

В общем, мы используем совместимый со стандартом PSR-2 стиль, так что все положения PSR-2 вполне применимы к нашему стилю кодирования.

  • ДОЛЖНЫ использоваться только открывающие теги <?php или <?=;
  • В конце файла должна быть пустая строка;
  • Файлы PHP кодом ДОЛЖНЫ содержать только символы в кодировке UTF-8 без BOM;
  • Для выравнивания кода НУЖНО использовать 4 пробела вместо табуляции;
  • Имена классов ДОЛЖНЫ быть объявлены используя StudlyCaps;
  • Константы класса ДОЛЖНЫ быть объявлены в верхнем регистре с подчеркиванием в качестве разделителей;
  • Имена методов ДОЛЖНЫ быть объявлены используя camelCase;
  • Имена свойств ДОЛЖНЫ быть объявлены используя camelCase;
  • Имена свойств ДОЛЖНЫ начинаться с подчеркивания если они объявлены с использованием модификатора private;
  • Всегда используйте elseif вместо else if.

2. Файлы

2.1. Теги PHP

  • В PHP коде ДОЛЖНЫ использоваться теги <?php ?> или <?=НЕ ДОЛЖНЫ использоваться другие теги, такие как <?;
  • Если файл содержит только PHP код, тогда закрывающий тег ?> не нужен;
  • Не добавляйте лишние пробелы в конец строки;
  • Все файлы, содержащие PHP код, должны иметь расширение .php.

2.2. Кодировка символов

PHP код ДОЛЖЕН содержать только символы в кодировке UTF-8 без BOM.

3. Имена Классов

Имена классов ДОЛЖНЫ быть определены используя StudlyCaps. Например, Controller, Model.

4. Классы

В данном случае, под классом подразумеваются все классы и интерфейсы.

  • При именовании классов следует использовать CamelCase;
  • Открывающая фигурная скобка всегда должна быть на следующей строке после имена класса;
  • Все классы должны быть документированы в соответствии с PHPDoc;
  • Весь код класса должен быть выровнен с использованием 4 пробелов;
  • В одном PHP файле должен быть только один класс;
  • Все классы должны использовать пространства имен;
  • Имя класса должно совпадать с именем файла. Пространство имен класса должно соответствовать структуре каталогов.
/**
* Документация
*/
class MyClass extends \yii\Object implements MyInterface
{
    // код
}

4.1. Константы

Константы класса ДОЛЖНЫ быть объявлены в верхнем регистре с подчеркиванием в качестве разделителей. Пример:

<?php
class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}

4.2. Свойства

  • При объявлении общедоступных (public) членов класса нужно использовать ключевое слово public;
  • Общедоступные и защищенные (protected) переменные должны быть объявлены в начале класса, раньше объявления методов; Закрытые (private) переменные, так же, должны быть объявлены в начале класса, но могут быть добавлены и непосредственно перед методами, использующими их, в случае, если эти переменные используются только небольшой частью методов класса;
  • Порядок объявления свойств класса должен соответствовать их видимости: общедоступные, защищенные и закрытые;
  • Ограничений на порядок свойств одной области видимости нет;
  • Для улучшения читаемости, следует не оставлять пустых строк между объявлением свойств и оставлять две пустые строки между объявлениями переменных и методов. Между объявлениями свойств разной области видимости нужно должна быть добавлена одна пустая строка;
  • Закрытые переменные должны иметь имя вида $_varName;
  • Общедоступные члены класса и отдельные переменные должны использовать $camelCase с первой буквой в нижнем регистре;
  • Используйте понятные имена. Переменные вроде $i и $j лучше не использовать.

Пример:

<?php
class Foo
{
    public $publicProp1;
    public $publicProp2;

    protected $protectedProp;

    private $_privateProp;


    public function someMethod()
    {
        // ...
    }
}

4.3. Методы

  • При именовании методов и функций следует использовать camelCase с первой буквой в нижнем регистре;
  • Имена должны быть понятными и отражать назначение функции;
  • Методы классов должны быть объявлены с использованием одного из модификаторов private, protected или public. Использование var недопустимо;
  • Открывающая фигурная кавычка должна быть расположена на строке, следующей за строкой объявления функции.
/**
 * Документация
 */
class Foo
{
    /**
     * Документация
     */
    public function bar()
    {
        // код
        return $value;
    }
}

4.4 Блоки Документации

@param, @var, @property и @return должны описывать типы boolean, integer, string, array или null. Вы можете использовать и имена классов, например Model или ActiveRecord. Для типизированных массивов используйте ClassName[].

4.5 Конструкторы

Используйте __construct вместо старого стиля, применяемого в PHP 4.

5 PHP

5.1 Типы Данных

  • Все типы данных и значения PHP должны быть в нижнем регистре. Это относится и к true, false, null и array.

Изменение типа существующей переменной считается плохой практикой. Постарайтесь не использовать такой подход, за исключением случаев, когда это действительно необходимо.

public function save(Transaction $transaction, $argument2 = 100)
{
    $transaction = new Connection; // плохо
    $argument2 = 200; // хорошо
}

5.2 Строки

  • Если строка не содержит переменных или одинарных кавычек, используйте одинарные кавычки;
$str = 'Например так.';
  • Если строка содержит одинарную кавычку, используйте двойные кавычки во избежание излишнего экранирования.
Подстановка переменных
$str1 = "Привет, $username!";
$str2 = "Привет, {$username}!";

Следующий вариант запрещен:

$str3 = "Привет, ${username}!";
Конкатенация

При конкатенации строк выделяйте точку пробелами:

$name = 'Yii' . ' Framework';

Для длинных строк используйте следующий подход:

$sql = "SELECT *"
    . "FROM `post` "
    . "WHERE `id` = 121 ";

5.3 Массивы

Для массивов мы используем краткий синтаксис [], появившийся в PHP 5.4.

Индексированные массивы

Не используйте отрицательные числа в качестве индексов массива.

Используйте следующий стиль:

$arr = [3, 14, 15, 'Yii', 'Framework'];

При большом количестве элементов:

$arr = [
    3, 14, 15,
    92, 6, $test,
    'Yii', 'Framework',
];
Ассоциативные массивы

Для ассоциативных массивов используйте следующий стиль:

$config = [
    'name' => 'Yii',
    'options' => ['usePHP' => true],
];

5.4 Управляющие конструкции

  • Оставляйте один пробел перед открывающей круглой скобкой и после закрывающей круглой скобки в управляющих конструкциях;
  • Операторы внутри круглых скобок должны разделяться пробелами;
  • Открывающая фигурная скобка должна быть на той же строке;
  • Закрывающая фигурная скобка должна быть на новой строке;
  • Всегда используйте фигурные скобки для однострочных выражений.
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 там, где это возможно. Используйте граничные операторы.

$result = $this->getResult();
if (empty($result)) {
    return true;
} else {
    // дальнейшие вычисления
}

лучше переписать так:

$result = $this->getResult();
if (empty($result)) {
    return true;
}

// дальнейшие вычисления
switch

Используйте следующий стиль для switch:

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 Вызовы функций

doIt(2, 3);

doIt(['a' => 'b']);

doIt('a', [
    'a' => 'b',
    'c' => 'd',
]);

5.6 Анонимные (lambda) функции

Не забывайте про пробелы между ключевыми словами function/use и открывающими круглыми скобками:

// правильно
$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;
  • Код без документации недопустим;
  • Все файлы классов должны содержать блок документации в начале файла и блок документации непосредственно перед каждым классом;
  • Нет необходимости использовать тег @return если метод не возвращает значение;
  • Все виртуальные свойства классов, наследованных от yii\base\Object, документируются тегом @property в блоке документации класса. Аннотации геттеров и сеттеров автоматически генерируются из соответствующих тегов @return or @param посредством выполнения команды ./build php-doc в соответствующем каталоге. Вы можете добавить дополнительный тег @property для геттера или сеттера для пояснения назначения переменной метода, если это необходимо. Например:
<?php
    /**
     * Returns the errors for all attribute or a single attribute.
     * @param string $attribute attribute name. Use null to retrieve errors for all attributes.
     * @property array An array of errors for all attributes. Empty array is returned if no error.
     * The result is a two-dimensional array. See [[getErrors()]] for detailed description.
     * @return array errors for all attributes or the specified attribute. Empty array is returned if no error.
     * Note that when returning errors for all attributes, the result is a two-dimensional array, like the following:
     * ...
     */
    public function getErrors($attribute = null)

Файл

<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

Класс

/**
 * Component is the base class that provides the *property*, *event* and *behavior* features.
 *
 * @include @yii/docs/base-Component.md
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Component extends \yii\base\Object

Функция / метод

/**
 * 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]].

Часть до | это имя свойства, метода или класса для ссылки, а часто поле | это текст ссылки.

Так же, возможно создание ссылок на Руководство:

[Руководство](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).

 

Перевод официальной документации.

5 thoughts on “Yii2: Современный стиль PHP кода

  1. Иван

    Автор, почему перестал писать, постоянно наблюдаю за этим сайтом, жду новых публикаций. Спасибо

  2. Alexey

    «Имена свойств ДОЛЖНЫ начинаться с подчеркивания если они объявлены с использованием модификатора private;
    Закрытые переменные должны иметь имя вида $_varName;»

    Возможно, это старая версия PSR-2, но на данный момент PSR-2 как раз рекомендует (не обязательно) использовать приватные методы и свойства без подчеркивания.

    Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.
    Method names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *