core-code-style.md 16.9 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 111

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

### 4.3. メソッド

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

~~~
/**
117
 * ドキュメント
118 119 120 121
 */
class Foo
{
    /**
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 147 148 149 150 151 152 153 154 155 156
     */
    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` にも当てはまります。

連想配列に対しては次の書式を使います:

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

157
既存の変数の型を変えることは悪い慣行であると見なされます。本当に必要でない限り、そのようなコードを書かないように努めましょう。
158 159 160 161 162 163 164 165 166 167 168 169


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

### 5.2 文字列

170
- 文字列が変数および一重引用符を含まない場合は、一重引用符を使います。
171 172 173 174 175

```php
$str = 'Like this.';
```

176
- 文字列が一重引用符を含む場合は、余計なエスケープを避けるために二重引用符を使ってもかまいません。
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

#### 変数置換

```php
$str1 = "Hello $username!";
$str2 = "Hello {$username}!";
```

下記は許可されません:

```php
$str3 = "Hello ${username}!";
```

#### 連結

文字列を連結するときは、ドットの周囲に空白を追加します:

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

文字列が長い場合、書式は以下のようにします:

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

### 5.3 配列

209
配列には、私たちは PHP 5.4 の短縮構文を使用しています。
210 211 212 213 214 215 216 217 218 219 220

#### 添え字配列

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

配列を宣言するときは、下記の書式を使います:

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

221
一つの行には多過ぎるほど要素がたくさんある場合は:
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

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

#### 連想配列

連想配列には下記の書式を使います:

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

### 5.4 制御文

- 制御文の条件は括弧の前と後に一つの空白を持たなければなりません。
- 括弧の中の演算子は空白によって区切られるべきです。
246 247 248
- 開始の中括弧は同じ行に置きます。
- 終了の中括弧は新しい行に置きます。
- 単一行の文に対しても、常に中括弧を使用します。
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263

```php
if ($event === null) {
    return new Event();
} elseif ($event instanceof CoolEvent) {
    return $event->instance();
} else {
    return null;
}

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

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
そうすることが合理的な場合は、`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 を処理
```

287 288
#### switch

289
switch には下記の書式を使用します。
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

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

323
`function`/`use` トークンと開始括弧の間の空白に注意してください。
324 325 326 327 328 329 330 331 332 333

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

334
// 悪い
335 336 337 338 339 340 341 342
$n = 100;
$mul = array_reduce($numbers, function($r, $x) use($n) {
    $this->doMagic();
    $r *= $x * $n;
    return $r;
});
```

343 344
ドキュメント
------------
345

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

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

373 374
>Note|注意: ここでは読みやすさを考慮してドキュメントの内容を日本語に翻訳していますが
コアコードや公式エクステンションに対して寄稿する場合は当然ながらコメントには英語だけを使う必要があるでしよう
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 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431

#### ファイル

```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

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

432
ドキュメントの中でクラス、メソッド、プロパティをクロスリンクするために使える追加の文法があります。
433 434 435 436 437 438

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

439
上記のリンクにクラス名やメソッド名以外のラベルを付けるためには、次の例で示されている文法を使うことが出来ます。
440 441 442 443 444 445 446

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

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

447
下記の文法を使ってガイドにリンクすることも可能です:
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464

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


#### コメント

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

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

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

465
可能な場合は `empty()` を使います。
466 467 468

### 複数の return ポイント

469
条件の入れ子が込み入ってきた場合は、早期の return を使います。メソッドが短いものである場合は、特に問題にしません。
470 471 472 473 474 475 476 477 478 479 480

### `self` 対 `static`

以下の場合を除いて、常に `static` を使います:

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

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

481 482
コンポーネントに対して「何かをしない」という設定を許可するプロパティは `false` の値を受け入れるべきです。
`null``''`、または `[]` がそういう値であると見なされるべきではありません。
483 484 485 486 487 488

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

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