PHP
PSR
PSR-12

PSR-12 Extended Coding Style Guide

More than 1 year has passed since last update.

PSR一覧
PSR-5 / PSR-6 / PSR-11 / PSR-12 / PSR-14 / PSR-16

PSR-12は古くなったPSR-2の置き換えです。
端的に言うとPHP7への対応でしょう。
2016/03/29現在まだDraftなので変わる可能性があります。

特に全文和訳する気はないので適当に抜き出してみました。
例によって英語は斜め読みなのであまり信用しないように。

1. Overview

  • PSR-12はPSR-2の延長で拡張で置き換えだぜ。
<?php
declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\Namespace\ClassD as D;

use function Vendor\Package\{functionA, functionB, functionC};
use const Vendor\Package\{ConstantA, ConstantB, ConstantC};

class Foo extends Bar implements FooInterface
{
    public function sampleFunction(int $a, int $b = null): array
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}

例示は基本的にPSR-12からのコピペです。

2. General

2.5 Keywords and Types以外はPSR-2と同じ。
禁止ワードがtrue, false, nullからarray, int, true, object, float, false, mixed, bool, null, numeric, string, void, resourceに増えた。

3. Declare Statements, Namespace, and Use Declarations

  • decrareについて、strict_typesがある場合は<?phpの次の行に書く、decrareはそれぞれ改行する、decrareの後は1行空ける。

  • useはグループ化できるならグループ化する、前後に1行空ける、。
    useの順番はclass、function、constの順。
    2段階以上異なるnamespaceをグループ化してはいけない。

use A\B{ C\D,   F } // これはOK
use A\B{ C\D\E, F } // こっちはNG
  • 1行目の<?phpの行にはそれ以外を書いてはいけない。 ただしテンプレートファイルなどでstrict_typesしたい場合は、以下のように1行目に開始タグ、strict_typeの宣言、終了タグを書かなければならない。
<?php declare(strict_types=1); ?>
<html>
  以下略

4. Classes, Properties, and Methods

  • 閉じ中括弧にコメントを書いてはいけない。
  if($hoge){
    // 長い行
  } // endif($hoge)

みたいな書き方はいけないらしい。
これは実用的にわりと困りそう
ifを長くするんじゃないとか言われてもテンプレート内とかだと難しいんだよね。

  • クラスをnewするときに()を略してはいけない。
  new stdClass(); // OK
  new stdClass;   // NG
  • クラス名定義のextendsとimplementsは1行で書かないといけない。
  • implementsは長くなりそうなら改行して書いてよいが、その場合は必ずひとつごとに改行する。
  • {}はそれぞれ単独行にする。
class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable
{
    // 本体
}

個人的に{で単独行取るのが好きではない。
特に全部揃ってるならまだマシなんだが、ifとかuseとかは改行しないからなんでだよってなる。

  • トレイトは{直後に書かないといけない。ひとつごとに改行する。
  • トレイト以外何もない場合はuseの後1行空けずに}で閉じる。
  • 他に何かある場合は1行空けて続ける。
class ClassName
{
    use FirstTrait;
    use SecondTrait;
}
  • プロパティのアクセス修飾子は必ず明記する。varは使用不可。
  • アクセス権を示すためにプロパティ名の_を使ってはいけない。
  • 意味を持たせずに使うのは問題ないようだ。
class ClassName
{
    public $foo = null;
}
  • メソッドのアクセス修飾子は必ず明記する。
  • アクセス権を示すためにメソッド名の_を使ってはいけない。
  • メソッドの{}は単独行で書く。
  • 引数の,は、前にはスペース不要、後ろには必要。
  • スカラータイプヒンティングは小文字で書く。
  • 引数が長くなる場合は改行してよいが、その場合は引数ひとつごとに改行する。その場合のみ引数閉じ括弧と本体始まりを1行で書く。
  • 返り値のタイプヒンティングは):はスペース無し、その後はスペースひとつ。
  • abstract、finalはアクセス修飾子より先に書く。
  • staticはアクセス修飾子より後ろに書く。
    final public function fooBar($arg1): string
    {
        // 関数はアクセス修飾子がないだけで他は同じ
    }

    public static function fooBarBaz(
        int $arg1,
        &$arg2,
        $arg3 = []
    ) {
        // 本体
    }

引数改行しつつの返り値タイプヒンティングは ): string { でいいんじゃろか。

  • メソッドや関数呼び出しは、,の後以外スペースを空けない。
  • 引数が長くなる場合は改行してよいが、その場合は引数ひとつごとに改行する。
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

somefunction($foo, $bar, [
  $hoge,
  $fuga
], $baz);

5. Control Structures

finallyが増えたくらいで、他はPSR-2と全く同じ。

6. Operators

演算子の項目が増えた。

  • !以外の代数/比較/代入/ビット/論理/文字列/型演算子は前後にスペースが必要。
  • それ以外は未定。
if ($a === $b) {
    $foo = $bar ?? $a ?? $b;
} elseif ($a > $b) {
    $variable = $foo ? 'foo' : 'bar';
}

~や++みたいな単項演算子はスペース不要でいいと思うのだがどうか。

7. Closures

PSR-2と同じ。

8. Anonymous Classes

  • 無名クラスはクロージャと同じルールに従う。
$instance = new class extends \Foo implements \HandleableInterface {
    // 本文
};

// Parenthesis on the next line
$instance = new class extends \Foo implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // 本文
};

クラスは{を改行しないといけなかったのに、こっちはくっつけていいとか一貫してないよなあ。

参考