Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 138 KiB |
@ -0,0 +1,477 @@
|
||||
Стиль кодирования Yii2 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 кодом ДОЛЖНЫ содержать только символы в кодировке 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 файле должен быть только один класс; |
||||
- Все классы должны использовать пространства имен; |
||||
- Имя класса должно совпадать с именем файла. Пространство имен класса должно соответствовать структуре каталогов. |
||||
|
||||
```php |
||||
/** |
||||
* Документация |
||||
*/ |
||||
class MyClass extends \yii\Object implements MyInterface |
||||
{ |
||||
// код |
||||
} |
||||
``` |
||||
|
||||
### 4.1. Константы |
||||
|
||||
Константы класса ДОЛЖНЫ быть объявлены в верхнем регистре с подчеркиванием в качестве разделителей. |
||||
Пример: |
||||
|
||||
```php |
||||
<?php |
||||
class Foo |
||||
{ |
||||
const VERSION = '1.0'; |
||||
const DATE_APPROVED = '2012-06-01'; |
||||
} |
||||
``` |
||||
### 4.2. Свойства |
||||
|
||||
- При объявлении общедоступных (public) членов класса нужно использовать ключевое слово `public`; |
||||
- Общедоступные и защищенные (protected) переменные должны быть объявлены в начале класса, раньше объявления методов; |
||||
Закрытые (private) переменные, так же, должны быть объявлены в начале класса, но могут быть добавлены и непосредственно перед методами, использующими их, в случае, если эти переменные используются только небольшой частью методов класса; |
||||
- Порядок объявления свойств класса должен соответствовать их видимости: общедоступные, защищенные и закрытые; |
||||
- Ограничений на порядок свойств одной области видимости нет; |
||||
- Для улучшения читаемости, следует не оставлять пустых строк между объявлением свойств и оставлять две пустые строки между объявлениями переменных и методов. Между объявлениями свойств разной области видимости нужно должна быть добавлена одна пустая строка; |
||||
- Закрытые переменные должны иметь имя вида `$_varName`; |
||||
- Общедоступные члены класса и отдельные переменные должны использовать `$camelCase` |
||||
с первой буквой в нижнем регистре; |
||||
- Используйте понятные имена. Переменные вроде `$i` и `$j` лучше не использовать. |
||||
|
||||
Пример: |
||||
|
||||
```php |
||||
<?php |
||||
class Foo |
||||
{ |
||||
public $publicProp1; |
||||
public $publicProp2; |
||||
|
||||
protected $protectedProp; |
||||
|
||||
private $_privateProp; |
||||
|
||||
|
||||
public function someMethod() |
||||
{ |
||||
// ... |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### 4.3. Методы |
||||
|
||||
- При именовании методов и функций следует использовать `camelCase` с первой буквой в нижнем регистре; |
||||
- Имена должны быть понятными и отражать назначение функции; |
||||
- Методы классов должны быть объявлены с использованием одного из модификаторов `private`, `protected` или |
||||
`public`. Использование `var` недопустимо; |
||||
- Открывающая фигурная кавычка должна быть расположена на строке, следующей за строкой объявления функции. |
||||
|
||||
```php |
||||
/** |
||||
* Документация |
||||
*/ |
||||
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`. |
||||
|
||||
Изменение типа существующей переменной считается плохой практикой. Постарайтесь не использовать такой подход, за исключением случаев, когда это действительно необходимо. |
||||
|
||||
|
||||
```php |
||||
public function save(Transaction $transaction, $argument2 = 100) |
||||
{ |
||||
$transaction = new Connection; // плохо |
||||
$argument2 = 200; // хорошо |
||||
} |
||||
``` |
||||
|
||||
### 5.2 Строки |
||||
|
||||
- Если строка не содержит переменных или одинарных кавычек, используйте одинарные кавычки; |
||||
|
||||
```php |
||||
$str = 'Например так.'; |
||||
``` |
||||
|
||||
- Если строка содержит одинарную кавычку, используйте двойные кавычки во избежание излишнего экранирования. |
||||
|
||||
#### Подстановка переменных |
||||
|
||||
```php |
||||
$str1 = "Привет, $username!"; |
||||
$str2 = "Привет, {$username}!"; |
||||
``` |
||||
|
||||
Следующий вариант запрещен: |
||||
|
||||
```php |
||||
$str3 = "Привет, ${username}!"; |
||||
``` |
||||
|
||||
#### Конкатенация |
||||
|
||||
При конкатенации строк выделяйте точку пробелами: |
||||
|
||||
```php |
||||
$name = 'Yii' . ' Framework'; |
||||
``` |
||||
|
||||
Для длинных строк используйте следующий подход: |
||||
|
||||
```php |
||||
$sql = "SELECT *" |
||||
. "FROM `post` " |
||||
. "WHERE `id` = 121 "; |
||||
``` |
||||
|
||||
### 5.3 Массивы |
||||
|
||||
Для массивов мы используем краткий синтаксис, появившийся в PHP 5.4. |
||||
|
||||
#### Индексированные массивы |
||||
|
||||
- Не используйте отрицательные числа в качестве индексов массива. |
||||
|
||||
Используйте следующий стиль: |
||||
|
||||
```php |
||||
$arr = [3, 14, 15, 'Yii', 'Framework']; |
||||
``` |
||||
|
||||
При большом количестве элементов: |
||||
|
||||
```php |
||||
$arr = [ |
||||
3, 14, 15, |
||||
92, 6, $test, |
||||
'Yii', 'Framework', |
||||
]; |
||||
``` |
||||
|
||||
#### Ассоциативные массивы |
||||
|
||||
Для ассоциативных массивов используйте следующий стиль: |
||||
|
||||
```php |
||||
$config = [ |
||||
'name' => '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\Object`, документируются тегом `@property` в блоке документации класса; |
||||
Аннотации геттеров и сеттеров автоматически генерируются из соответствующих тегов `@return` or `@param` |
||||
посредством выполнения команды `./build php-doc` в соответствующем каталоге; |
||||
Вы можете добавить дополнительный тег `@property` для геттера или сеттера для пояснения назначения переменной метода, если это необходимо. |
||||
Например: |
||||
|
||||
```php |
||||
<?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 |
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
``` |
||||
|
||||
#### Класс |
||||
|
||||
```php |
||||
/** |
||||
* 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 |
||||
``` |
||||
|
||||
|
||||
#### Функция / метод |
||||
|
||||
```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`, `''`, or `[]` не должны использоваться в таких случаях. |
||||
|
||||
### Каталоги/пространства имен |
||||
|
||||
- Используйте нижний регистр; |
||||
- используйте множественную форму для существительных, представляющих объекты (например валидаторы); |
||||
- используйте единичную форму для имен, представляющих соответствующий функционал (например web). |
@ -0,0 +1,75 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yiiunit\data\base; |
||||
|
||||
/** |
||||
* TraversableObject |
||||
* Object that implements `\Traversable` and `\Countable`, but counting throws an exception; |
||||
* Used for testing support for traversable objects instead of arrays. |
||||
* @author Sam Mousa <sam@mousa.nl> |
||||
* @since 2.0.8 |
||||
*/ |
||||
class TraversableObject implements \Iterator, \Countable |
||||
{ |
||||
private $data; |
||||
private $position = 0; |
||||
|
||||
public function __construct(array $array) |
||||
{ |
||||
$this->data = $array; |
||||
} |
||||
|
||||
/** |
||||
* @throws \Exception |
||||
* @since 5.1.0 |
||||
*/ |
||||
public function count() |
||||
{ |
||||
throw new \Exception('Count called on object that should only be traversed.'); |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function current() |
||||
{ |
||||
return $this->data[$this->position]; |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function next() |
||||
{ |
||||
$this->position++; |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function key() |
||||
{ |
||||
return $this->position; |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function valid() |
||||
{ |
||||
return array_key_exists($this->position, $this->data); |
||||
} |
||||
|
||||
/** |
||||
* @inheritdoc |
||||
*/ |
||||
public function rewind() |
||||
{ |
||||
$this->position = 0; |
||||
} |
||||
} |