Yii2 コアフレームワークのコードスタイル ======================================= 下記のコードスタイルが Yii 2.x コアと公式エクステンションの開発に用いられています。 コアに対してコードをプルリクエストをしたいときは、これを使用することを考慮してください。 私たちは、あなたが自分のアプリケーションにこのコードスタイルを使うことを強制するものではありません。 あなたにとってより良いコードスタイルを自由に選んでください。 なお、CodeSniffer のための設定をここで入手できます: https://github.com/yiisoft/yii2-coding-standards > Note: 以下では、説明のために、サンプル・コードのドキュメントやコメントを日本語に翻訳しています。 しかし、コアコードや公式エクステンションに対して実際に寄稿する場合には、それらを英語で書く必要があります。 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 コードは BOM 無しの UTF-8 のみを使わなければなりません。 3. クラス名 ----------- クラス名は `StudlyCaps` で宣言されなければなりません。例えば、`Controller`、`Model`。 4. クラス --------- ここで "クラス" という用語はあらゆるクラスとインタフェイスを指すものとします。 - クラスは `CamelCase` で命名されなければなりません。 - 中括弧は常にクラス名の下の行に書かれるべきです。 - 全てのクラスは PHPDoc に従ったドキュメントブロックを持たなければなりません。 - クラス内のすべてのコードは4個の空白によってインデントされなければなりません。 - 一つの PHP ファイルにはクラスが一つだけあるべきです。 - 全てのクラスは名前空間に属すべきです。 - クラス名はファイル名と合致すべきです。クラスの名前空間はディレクトリ構造と合致すべきです。 ```php /** * ドキュメント */ class MyClass extends \yii\Object 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'); ``` そうしても意味が通じる場合は、`return` の後の `else` は避けてください。 [ガード条件](http://refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html) を使用しましょう。 ```php $result = $this->getResult(); if (empty($result)) { return true; } else { // $result を処理 } ``` これは、次の方が良いです。 ```php $result = $this->getResult(); if (empty($result)) { return true; } // $result を処理 ``` #### switch switch には下記の書式を使用します。 ```php switch ($this->phpType) { case 'string': $a = (string)$value; break; case 'integer': case 'int': $a = (integer)$value; break; case 'boolean': $a = (boolean)$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/) を参照してください。 - ドキュメントの無いコードは許容されません。 - 全てのクラスファイルは、ファイルレベルの doc ブロックを各ファイルの先頭に持ち、クラスレベルの doc ブロックを各クラスの直前に持たなければなりません。 - メソッドが実際に何も返さないときは `@return` を使う必要はありません。 - `yii\base\Object` から派生するクラスのすべての仮想プロパティは、クラスの doc ブロックで `@property` タグでドキュメントされます。 これらの注釈は、`build` ディレクトリで `./build php-doc` コマンドを走らせることにより、対応する getter や setter の `@return` や `@param` タグから自動的に生成されます。 getter や setter に `@property` タグを追加することによって、これらのメソッドによって導入されるプロパティに対してドキュメントのメッセージを明示的に与えることが出来ます。 これは `@return` で記述されているのとは違う説明を与えたい場合に有用です。 下記が一例です。 ```php * @since 2.0 */ class Component extends \yii\base\Object ``` #### 関数 / メソッド ```php /** * イベントに対してアタッチされたイベントハンドラのリストを返す。 * 返された [[Vector]] オブジェクトを操作して、ハンドラを追加したり削除したり出来る。 * 例えば、 * * ``` * $component->getEventHandlers($eventName)->insertAt(0, $eventHandler); * ``` * * @param string $name イベントの名前 * @return Vector イベントにアタッチされたハンドラのリスト * @throws Exception イベントが定義されていない場合 */ public function getEventHandlers($name) { if (!isset($this->_e[$name])) { $this->_e[$name] = new Vector; } $this->ensureBehaviors(); return $this->_e[$name]; } ``` #### Markdown 上記の例に見られるように、phpDoc コメントの書式設定には markdown を使います。 ドキュメントの中でクラス、メソッド、プロパティをクロスリンクするために使える追加の文法があります。 - `'[[canSetProperty]] ` は、同じクラス内の `canSetProperty` メソッドまたはプロパティへのクロスリンクを生成します。 - `'[[Component::canSetProperty]]` は、同じ名前空間内の `Component` クラスの `canSetProperty` メソッドへのクロスリンクを生成します。 - `'[[yii\base\Component::canSetProperty]]` は、`yii\base` 名前空間の`Component` クラスの `canSetProperty` メソッドへのクロスリンクを生成します。 - `'[[Component]]` は、同じ名前空間内の `Component` クラスへのクロスリンクを生成します。ここでも、クラス名に名前空間を追加することが可能です。 上記のリンクにクラス名やメソッド名以外のラベルを付けるためには、次の例で示されている文法を使うことが出来ます。 ``` ... [[header|ヘッダセル]] に表示されているように ``` `|` の前の部分がメソッド、プロパティ、クラスへの参照であり、`|` の後ろの部分がリンクのラベルです。 下記の文法を使ってガイドにリンクすることも可能です。 ```markdown [ガイドへのリンク](guide:file-name.md) [ガイドへのリンク](guide:file-name.md#subsection) ``` #### コメント - 一行コメントは `//` で開始されるべきです。`#` は使いません。 - 一行コメントはそれ自体で一行を占めるべきです。 追加の規則 ---------- ### `=== []` 対 `empty()` 可能な場合は `empty()` を使います。 ### 複数の return ポイント 条件の入れ子が込み入ってきた場合は、早期の return を使います。メソッドが短いものである場合は、特に問題にしません。 ### `self` 対 `static` 以下の場合を除いて、常に `static` を使います。 - 定数へのアクセスには `self` を使わなければなりません: `self::MY_CONSTANT` - private な静的プロパティへのアクセスには `self` を使わなければなりません: `self::$_events` - 再帰呼出しにおいて、拡張クラスの実装ではなく、現在のクラスの実装を再び呼び出したいときには、`self` を使うことが許可されます。 ### 「何かをするな」を示す値 コンポーネントに対して「何かをしない」という設定を許可するプロパティは `false` の値を受け入れるべきです。 `null`、`''`、または `[]` がそういう値であると見なされるべきではありません。 ### ディレクトリ/名前空間の名前 - 小文字を使います。 - オブジェクトを表すものには複数形の名詞を使います (例えば、validators)。 - 機能や特徴を表す名前には単数形を使います (例えば、web)。 - 出来れば単一の語の名前空間にします。 - 単一の語が適切でない場合は、camelCase を使います。