core-code-style.md 16.7 KB
Newer Older
1 2 3 4
Yii2 コアフレームワークのコードスタイル
=======================================

下記のコードスタイルが Yii 2.x コアと公式エクステンションの開発に用いられています。
5
コアに対してコードをプルリクエストをしたいときは、これを使用することを考慮してください。
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
私たちは、あなたが自分のアプリケーションにこのコードスタイルを使うことを強制するものではありません。
あなたにとってより良いコードスタイルを自由に選んでください。

なお、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 コードに対して BOM 無しの UTF-8 だけを使わなければならない。
- コードはインデントに、タブではなく、4個の空白を使わなければならない。
- クラス名は `StudlyCaps` で宣言されなくてはならない。
- クラス内の定数はアンダースコアで区切られた大文字だけで宣言されなければならない。
- メソッド名は `camelCase` で宣言されなければならない。
- プロパティ名は `camelCase` で宣言されなければならない。
25
- プロパティ名は private である場合はアンダースコアで始まらなければならない。
26 27 28 29 30 31 32
- `else if` ではなく常に `elseif` を使用すること。

2. ファイル
-----------

### 2.1. PHP タグ

33
- PHP コードは `<?php ?>` または `<?=` タグを使わなければなりません。他のタグの変種、例えば `<?` を使ってはなりません。
34
- ファイルが PHP コードのみを含む場合は、末尾の `?>` を含むべきではありません。
35
- 各行の末尾に空白を追加してはいけません。
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
- PHP コードを含む全てのファイルの名前は `.php` という拡張子で終るべきです。

### 2.2. 文字エンコーディング

PHP コードは BOM 無しの UTF-8 のみを使わなければなりません。

3. クラス名
-----------

クラス名は `StudlyCaps` で宣言されなければなりません。例えば、`Controller``Model`

4. クラス
---------

ここで "クラス" という用語はあらゆるクラスとインタフェイスを指すものとします。

- クラスは `CamelCase` で命名されなければなりません。
- 中括弧は常にクラス名の下の行に書かれるべきです。
54
- 全てのクラスは PHPDoc に従ったドキュメントブロックを持たなければなりません。
55
- クラス内のすべてのコードは一個のタブによってインデントされなければなりません。
56
- 一つの PHP ファイルにはクラスが一つだけあるべきです。
57
- 全てのクラスは名前空間に属すべきです。
58
- クラス名はファイル名と合致すべきです。クラスの名前空間はディレクトリ構造と合致すべきです。
59 60 61

```php
/**
62
 * ドキュメント
63 64 65
 */
class MyClass extends \yii\Object implements MyInterface
{
66
    // コード
67 68 69 70 71 72
}
```

### 4.1. 定数

クラスの定数はアンダースコアで区切られた大文字だけで宣言されなければなりません。
73
例えば、
74 75 76 77 78 79 80 81 82 83 84

```php
<?php
class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}
```
### 4.2. プロパティ

85
- Public なクラスメンバを宣言するときは `public` キーワードを明示的に指定します。
86 87
- Public および protected な変数はクラスの冒頭で、すべてのメソッドの宣言に先立って宣言されるべきです。
  Private な変数もまたクラスの冒頭で宣言されるべきですが、
88
  変数がクラスのメソッドのごく一部分にのみ関係する場合は、変数を扱う一群のメソッドの直前に追加しても構いません。
89 90 91
- クラスにおけるプロパティの宣言の順序は public から始まり、protected、private と続くべきです。
- より読みやすいように、プロパティの宣言は空行を挟まずに続け、プロパティ宣言とメソッド宣言のブロック間には2行の空行を挟むべきです。
- Private 変数は `$_varName` のように名付けるべきです。
92
- Public なクラスメンバとスタンドアロンな変数は、先頭を小文字にした `$camelCase` で名付けるべきです。
93 94
- 説明的な名前を使うこと。`$i``$j` のような変数は使わないようにしましょう。

95
例えば、
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

```php
<?php
class Foo
{
    public $publicProp;
    protected $protectedProp;
    private $_privateProp;
}
```

### 4.3. メソッド

- 関数およびメソッドは、先頭を小文字にした `camelCase` で名付けるべきです。
- 名前は、関数の目的を示す自己説明的なものであるべきです。
111
- クラスのメソッドは常に修飾子 `private``protected` または `public` を使って、可視性を宣言すべきです。`var` は許可されません。
112 113 114 115
- 関数の開始の中括弧は関数宣言の次の行に置くべきです。

~~~
/**
116
 * ドキュメント
117 118 119 120
 */
class Foo
{
    /**
121
     * ドキュメント
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
     */
    public function bar()
    {
        // コード
        return $value;
    }
}
~~~

### 4.4 Doc ブロック

`@param``@var``@property` および `@return``boolean``integer``string``array` または `null` として型を宣言しなければなりません。
`Model` または `ActiveRecord` のようなクラス名を使うことも出来ます。
型付きの配列に対しては `ClassName[]` を使います。

### 4.5 コンストラクタ

- PHP 4 スタイルのコンストラクタの代りに、`__construct` が使われるべきです。

## 5 PHP

### 5.1 型

- PHP の全ての型と値には小文字を使うべきです。このことは、`true``false``null` および `array` にも当てはまります。

147
既存の変数の型を変えることは悪いプラクティスであると見なされています。本当に必要でない限り、そのようなコードを書かないように努めましょう。
148 149 150 151 152 153 154 155 156 157 158 159


```php
public function save(Transaction $transaction, $argument2 = 100)
{
    $transaction = new Connection; // 駄目
    $argument2 = 200; // 良い
}
```

### 5.2 文字列

160
- 文字列が変数および一重引用符を含まない場合は、一重引用符を使います。
161 162

```php
163
$str = 'こんな具合に。';
164 165
```

166
- 文字列が一重引用符を含む場合は、余計なエスケープを避けるために二重引用符を使ってもかまいません。
167 168 169 170

#### 変数置換

```php
171 172
$str1 = "こんにちは $username さん";
$str2 = "こんにちは {$username} さん";
173 174
```

175
下記は許可されません。
176 177

```php
178
$str3 = "こんにちは ${username} さん";
179 180 181 182
```

#### 連結

183
文字列を連結するときは、ドットの前後に空白を追加します。
184 185 186 187 188

```php
$name = 'Yii' . ' Framework';
```

189
文字列が長い場合、書式は以下のようにします。
190 191 192 193 194 195 196 197 198

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

### 5.3 配列

199
配列には、私たちは PHP 5.4 の短縮構文を使用しています。
200 201 202 203 204

#### 添え字配列

- 負の数を配列のインデックスに使わないこと。

205
配列を宣言するときは、下記の書式を使います。
206 207 208 209 210

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

211
一つの行には多過ぎるほど要素がたくさんある場合は、
212 213 214 215 216 217 218 219 220 221 222

```php
$arr = [
    3, 14, 15,
    92, 6, $test,
    'Yii', 'Framework',
];
```

#### 連想配列

223
連想配列には下記の書式を使います。
224 225 226 227 228 229 230 231 232 233 234 235

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

### 5.4 制御文

- 制御文の条件は括弧の前と後に一つの空白を持たなければなりません。
- 括弧の中の演算子は空白によって区切られるべきです。
236 237 238
- 開始の中括弧は同じ行に置きます。
- 終了の中括弧は新しい行に置きます。
- 単一行の文に対しても、常に中括弧を使用します。
239 240 241 242

```php
if ($event === null) {
    return new Event();
243 244
}
if ($event instanceof CoolEvent) {
245 246
    return $event->instance();
}
247
return null;
248

249 250

// 下記は許容されません
251 252 253 254
if (!$model && null === $event)
    throw new Exception('test');
```

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
そうすることが合理的な場合は、`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 を処理
```

278 279
#### switch

280
switch には下記の書式を使用します。
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

```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) の宣言

314
`function`/`use` トークンと開始括弧の間の空白に注意してください。
315 316 317 318 319 320 321 322 323 324

```php
// 良い
$n = 100;
$sum = array_reduce($numbers, function ($r, $x) use ($n) {
    $this->doMagic();
    $r += $x * $n;
    return $r;
});

325
// 悪い
326 327 328 329 330 331 332 333
$n = 100;
$mul = array_reduce($numbers, function($r, $x) use($n) {
    $this->doMagic();
    $r *= $x * $n;
    return $r;
});
```

334 335
ドキュメント
------------
336

337 338
- ドキュメントの文法については [phpDoc](http://phpdoc.org/) を参照してください。
- ドキュメントの無いコードは許容されません。
339
- 全てのクラスファイルは、ファイルレベルの doc ブロックを各ファイルの先頭に持ち、クラスレベルの doc ブロックを各クラスの直前に持たなければなりません。
340
- メソッドが実際に何も返さないときは `@return` を使う必要はありません。
341
- `yii\base\Object` から派生するクラスのすべての仮想プロパティは、クラスの doc ブロックで `@property` タグでドキュメントされます。
342 343
  これらの注釈は、`build` ディレクトリで `./build php-doc` コマンドを走らせることにより、対応する getter や setter の `@return``@param` タグから自動的に生成されます。
  getter や setter に `@property` タグを追加することによって、これらのメソッドによって導入されるプロパティに対してドキュメントのメッセージを明示的に与えることが出来ます。
344 345
  これは `@return` で記述されているのとは違う説明を与えたい場合に有用です。
  下記が一例です。
346 347 348 349 350 351 352 353 354

  ```php
    <?php
    /**
     * 全ての属性または一つの属性についてエラーを返す。
     * @param string $attribute 属性の名前。全ての属性についてエラーを取得するためには null を使う。
     * @property array 全ての属性に対するエラーの配列。エラーが無い場合は空の配列が返される。
     * 結果は二次元の配列である。詳細な説明は [[getErrors()]] を参照。
     * @return array 全ての属性または特定の属性に対するエラー。エラーが無い場合は空の配列が返される。
355
     * 全ての属性に対するエラーを返す場合、結果は、下記のような二次元の配列になる。
356 357 358 359 360
     * ...
     */
    public function getErrors($attribute = null)
  ```

361
>Note|注意: ここでは読みやすさを考慮してドキュメントの内容を日本語に翻訳していますがコアコードや公式エクステンションに対して寄稿する場合は当然ながらコメントには英語だけを使う必要があります
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416

#### ファイル

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

#### クラス

```php
/**
 * Component は *property**event* および *behavior* の機能を提供する基底クラスである。
 *
 * @include @yii/docs/base-Component.md
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @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

417
上記の例に見られるように、phpDoc コメントの書式設定には markdown を使います。
418

419
ドキュメントの中でクラス、メソッド、プロパティをクロスリンクするために使える追加の文法があります。
420 421 422 423 424 425

- `'[[canSetProperty]] ` は、同じクラス内の `canSetProperty` メソッドまたはプロパティへのクロスリンクを生成します。
- `'[[Component::canSetProperty]]` は、同じ名前空間内の `Component` クラスの `canSetProperty` メソッドへのクロスリンクを生成します。
- `'[[yii\base\Component::canSetProperty]]` は、`yii\base` 名前空間の`Component` クラスの `canSetProperty` メソッドへのクロスリンクを生成します。
- `'[[Component]]` は、同じ名前空間内の `Component` クラスへのクロスリンクを生成します。ここでも、クラス名に名前空間を追加することが可能です。

426
上記のリンクにクラス名やメソッド名以外のラベルを付けるためには、次の例で示されている文法を使うことが出来ます。
427 428 429 430 431 432 433

```
... [[header|ヘッダセル]] に表示されているように
```

`|` の前の部分がメソッド、プロパティ、クラスへの参照であり、`|` の後ろの部分がリンクのラベルです。

434
下記の文法を使ってガイドにリンクすることも可能です。
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451

```markdown
[ガイドへのリンク](guide:file-name.md)
[ガイドへのリンク](guide:file-name.md#subsection)
```


#### コメント

- 一行コメントは `//` で開始されるべきです。`#` は使いません。
- 一行コメントはそれ自身の行に置くべきです。

追加の規則
----------

### `=== []` 対 `empty()`

452
可能な場合は `empty()` を使います。
453 454 455

### 複数の return ポイント

456
条件の入れ子が込み入ってきた場合は、早期の return を使います。メソッドが短いものである場合は、特に問題にしません。
457 458 459

### `self` 対 `static`

460
以下の場合を除いて、常に `static` を使います。
461 462 463 464 465 466 467

- 定数へのアクセスには `self` を使わなければなりません: `self::MY_CONSTANT`
- private な静的プロパティへのアクセスには `self` を使わなければなりません: `self::$_events`
- 再帰呼出しにおいて、拡張クラスの実装ではなく、現在のクラスの実装を再び呼び出したいときには、`self` を使うことが許可されます。

### 「何かをするな」を示す値

468 469
コンポーネントに対して「何かをしない」という設定を許可するプロパティは `false` の値を受け入れるべきです。
`null``''`、または `[]` がそういう値であると見なされるべきではありません。
470 471 472 473 474 475

### ディレクトリ/名前空間の名前

- 小文字を使います。
- オブジェクトを表すものには複数形の名詞を使います (例えば、validators)
- 機能や特徴を表す名前には単数形を使います (例えば、web)