目次

PSR-12: Extended Coding Style

y2sunlight 2020-06-23

本章は、若干の補足を加筆してはいるものの単にPSRのサイトを日本語に翻訳したものに過ぎません。英語が堪能な方は原文をご参照下さい。翻訳に当たっては、基本的に機械翻訳を使い、理解できない部分は独断で意訳しております。拙い訳では御座いますが恥を忍んで投稿しておりますので、ご指摘など御座いましたらコメントを頂ければ幸いです。

関連記事


PSR-12: 拡張コーディングスタイル

原文より翻訳 PSR-12: Extended Coding Style 2020-06-30 現在

このドキュメントのキーワード MUST , MUST NOT , REQUIRED , SHALL , SHALL NOT , SHOULD , SHOULD NOT , RECOMMENDED , MAY 及び OPTIONAL は、 RFC 2119で説明されているように解釈して下さい。

RFC 2119の説明
MUST, REQUIRED, SHALL — 絶対必要
MUST NOT, SHALL NOT — 絶対禁止
SHOULD, RECOMMENDED — 推奨(但し、無視できる特定の正当な理由が存在するかもしれない)
SHOULD NOT — 推奨できない(但し、許可できる特定の正当な理由が存在するかもしれない)
MAY, OPTIONAL — オプション


1. 概観

この仕様は、コーディングスタイルガイドであるPSR-2を継承し、拡張して、置き換えました。基本的なコーディング標準であるPSR-1への準拠を必要とします。

PSR-2と同様に、この仕様の目的は、さまざまな作成者のコードを読む時の認識の摩擦を減らすことです。 これは、共有された一連のルールと、PHPコードのフォーマット方法に関する期待を列挙することによって行われます。このPSRは、コーディングスタイルツールが実装できる一連の方法を提供することを目指しており、プロジェクトは遵守を宣言でき、開発者は異なるプロジェクト間で簡単にこれを関連付けることができます。さまざまな作成者が複数のプロジェクトにわたって共同作業を行う場合、それらすべてのプロジェクト間で1つのガイドラインセットを使用すると役立ちます。従って、このガイドの利点はルール自体ではなく、それらのルールの共有にあります。

上記の原文
Like PSR-2, the intent of this specification is to reduce cognitive friction when scanning code from different authors. It does so by enumerating a shared set of rules and expectations about how to format PHP code. This PSR seeks to provide a set way that coding style tools can implement, projects can declare adherence to and developers can easily relate to between different projects. When various authors collaborate across multiple projects, it helps to have one set of guidelines to be used among all those projects. Thus, the benefit of this guide is not in the rules themselves but the sharing of those rules.

PSR-2は2012年に承認され、それ以降、PHPには多くの変更が加えられ、それはコーディングスタイルガイドラインに影響するものでした。PSR-2は、執筆時点では存在していたPHP機能の非常に包括的なものでしたが、新しい機能には非常に解釈の自由があります。従って、このPSRは、PSR-2の内容をより近代的なコンテキストで明確にし、新しい機能を利用できるようにして、そのエラッタ(errata)をPSR-2にバインドすることを目的としています。

以前の言語バージョン

このドキュメント全体を通して、プロジェクトでサポートされているPHPのバージョンにインストラクションが存在しない場合、それらは無視できます( MAY )。

この例では、以下で説明するルールの幾つかを簡単な概要として取り上げています:

<?php
 
declare(strict_types=1);
 
namespace Vendor\Package;
 
use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\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
    }
}


2. 全般

2.1 基本コーディング規約

コードは、PSR-1で概説されているすべてのルールに従う必要があります( MUST )。

PSR-1の「StudlyCaps」という用語は、各単語の最初の文字が最初の文字を含めて大文字になっている PascalCase として解釈する必要があります( MUST )。


2.2 ファイル

すべてのPHPファイルは、Unix LF(ラインフィード)の行末のみを使用する必要があります( MUST )。

すべてのPHPファイルは、空白以外の行で終わり、単一のLFで終端する必要があります( MUST )。

PHPのみを含むファイルからは、終了タグ( ?> )を省略しなければなりません( MUST )。


2.3 ライン

行の長さに厳しい制限があってはなりません( MUST NOT )。

行の長さのソフトな制限は120文字でなければなりません( MUST )。   行は80文字を超えるべきではありません( SHOULD NOT )。それより長い行は、それぞれ80文字以下の複数の後続行に分割すべきです。( SHOULD )。

行末に空白があってはいけません( MUST NOT )。

明示的に禁止されている場合を除き、読みやすさを向上させ、コードの関連ブロックを示すために、空行を追加できます( MAY )。

1行に複数のステートメントがあってはなりません( MUST NOT )。


2.4 インデント

コードは、インデントレベル毎に4スペースのインデントを使用する必要があり( MUST )、インデントにタブを使用してはなりません( MUST NOT )。


2.5 キーワードとタイプ

すべてのPHPで予約されているキーワードタイプは小文字でなければなりません( MUST )。

将来のPHPバージョンに追加される新しいタイプとキーワードは、小文字でなければなりません( MUST )。

Short form of type keywords MUST be used i.e. bool instead of boolean, int instead of integer etc.

タイプのキーワードは短い形式を使用する必要があります( MUST )。つまり、boolean の代わりに boolinteger の代わりに int などです。


3. Declare文、名前空間、およびインポート文

PHPファイルのヘッダーは、いくつかの異なるブロックで構成されている場合があります。存在するなら、以下の各ブロックは単一の空行で区切る必要があり( MUST )、各ブロックは空行を含んではいけません( MUST NOT )。 各ブロックは、以下にリストされている順序でなければなりませんが( MUST )、関連のないブロックは省略できます。

ファイルにHTMLとPHPが混在している場合でも、上記のセクションのいずれかを使用できます。その場合、コードの残りの部分がPHPの終了タグと、その後にHTMLとPHPの混合物で構成されている場合でも、それらはファイルの先頭に存在する必要があります( MUST )。

開始タグ( <?php )がファイルの最初の行にある場合、それがPHPの開始および終了タグの外側のマークアップを含むファイルでない限り、それは他のステートメントを含まない独自の行になければなりません( MUST )。

上記の原文
When the opening <?php tag is on the first line of the file, it MUST be on its own line with no other statements unless it is a file containing markup outside of PHP opening and closing tags.

原文自体が分かり難いが、これは下例のような場合以外は <?php の単独行にする意味だと思われます。
<?php declare(strict_types=1) ?>

インポート文は常に完全修飾されていなければならないので、決してバックスラッシュで始めてはなりません( MUST NOT )。

次の例は、すべてのブロックの完全なリストを示しています:

<?php
 
/**
 * This file contains an example of coding styles.
 * このファイルには、コーディングスタイルの例が含まれています。
 */
 
declare(strict_types=1);
 
namespace Vendor\Package;
 
use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\ClassD as D;
use Vendor\Package\AnotherNamespace\ClassE as E;
 
use function Vendor\Package\{functionA, functionB, functionC};
use function Another\Vendor\functionD;
 
use const Vendor\Package\{CONSTANT_A, CONSTANT_B, CONSTANT_C};
use const Another\Vendor\CONSTANT_D;
 
/**
 * FooBar is an example class.
 * FooBarはサンプルクラスです。
 */
class FooBar
{
    // ... additional PHP code ...
}

深度が2を超える複合名前空間は使用してはなりません( MUST NOT )。 従って、許容される最大の合成深度は次のとおりです:

<?php
 
use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\ClassA,
    SubnamespaceOne\ClassB,
    SubnamespaceTwo\ClassY,
    ClassZ,
};

また、以下は許可されません:

<?php
 
use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\AnotherNamespace\ClassA,
    SubnamespaceOne\ClassB,
    ClassZ,
};

PHPの開始タグと終了タグの外側のマークアップを含むファイルで厳密なタイプ( strict_types )を宣言したい時、宣言はファイルの最初の行にあり、PHPの開始タグ、厳密なタイプの宣言と終了タグ を含める必要があります( MUST )。

例えば:

<?php declare(strict_types=1) ?>
<html>
<body>
    <?php
        // ... additional PHP code ...
    ?>
</body>
</html>

declare文にはスペースを含めず( MUST )、正確に declare(strict_types=1)(オプションでセミコロンターミネータの使用可)とする必要があります( MUST )。

ブロックdeclare文は許可され、以下のようにフォーマットする必要があります( MUST )。中括弧( { } )の位置と間隔に注意してください:

declare(ticks=1) {
    // some code
}


4. クラス、プロパティ、メソッド

「クラス」という用語は、すべてのクラス、インターフェース、およびトレイトを指します。

どんな閉じ中括弧( } )の後にも、同じ行にコメントまたはステートメントを続けてはなりません( MUST NOT )。

新しいクラスをインスタンス化するとき、コンストラクターに渡される引数がない場合でも、丸括弧( () )は常に存在している必要があります( MUST )。

new Foo();


4.1 拡張および実装

extendsimplements キーワードは、クラス名と同じ行で宣言する必要があります( MUST )。

クラスの開き中括弧( { )は独自の行に配置する必要があります( MUST )。クラスの閉じ中括弧( } )は、本文の後の次の行に配置する必要があります( MUST )。

開き中括弧( { )は独自の行になければならず( MUST )、前後に空行があってはなりません( MUST NOT )。

閉じ中括弧( } )は独自の行になければならず( MUST )、前に空行があってはなりません( MUST NOT )。

<?php
 
namespace Vendor\Package;
 
use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
 
class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // constants, properties, methods
}

implements のリスト(インターフェースの場合)および extends は複数の行に分割されてもよく( MAY )、後続の各行は1回インデントされます。 そうする場合、実装リストの最初の項目は次の行になければならず( MUST )、1行に1つのインターフェースだけにする必要があります( MUST )。

<?php
 
namespace Vendor\Package;
 
use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
 
class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}


4.2 トレイトの使用

トレイトを実装するためにクラス内で使用される use キーワードは、クラスの開き中括弧( { )の後の次の行で宣言する必要があります( MUST )。

<?php
 
namespace Vendor\Package;
 
use Vendor\Package\FirstTrait;
 
class ClassName
{
    use FirstTrait;
}

クラスにインポートされる個々のトレイトは1行に1つずつ含める必要があり( MUST )、各インクルードには独自の use インポート文が必要です( MUST )。

<?php
 
namespace Vendor\Package;
 
use Vendor\Package\FirstTrait;
use Vendor\Package\SecondTrait;
use Vendor\Package\ThirdTrait;
 
class ClassName
{
    use FirstTrait;
    use SecondTrait;
    use ThirdTrait;
}

クラスが use インポート文の後に何もない場合、クラスの閉じ括弧は、useインポート文の後の次の行になければなりません( MUST )。

<?php
 
namespace Vendor\Package;
 
use Vendor\Package\FirstTrait;
 
class ClassName
{
    use FirstTrait;
}

それ以外の場合は、use インポート文の後に空行が必要です( MUST )。

<?php
 
namespace Vendor\Package;
 
use Vendor\Package\FirstTrait;
 
class ClassName
{
    use FirstTrait;
 
    private $property;
}

insteadofas 演算子を使用するときは、インデント、空白、改行に注意して、次のように使用する必要があります。

<?php
 
class Talker
{
    use A;
    use B {
        A::smallTalk insteadof B;
    }
    use C {
        B::bigTalk insteadof C;
        C::mediumTalk as FooBar;
    }
}


4.3 プロパティと定数

すべてのプロパティで可視性を宣言する必要があります( MUST )。

プロジェクトのPHPの最小バージョンが定数の可視性(PHP 7.1以降)をサポートしている場合は、すべての定数で可視性を宣言する必要があります( MUST )。

プロパティの宣言に var キーワードを使用してはなりません( MUST NOT )。

ステートメントごとに複数のプロパティを宣言することはできません( MUST NOT )。

protected または private な可視性を示すために、プロパティ名の前に単一のアンダースコア( _ )を付けてはいけません( MUST NOT )。つまり、アンダースコア( _ )のプレフィックスは明示的に意味を持ちません。

型宣言とプロパティ名の間にはスペースが必要です( MUST )。

プロパティ宣言は次のようになります:

<?php
 
namespace Vendor\Package;
 
class ClassName
{
    public $foo = null;
    public static int $bar = 0;
}


4.4 メソッドと関数

すべてのメソッドで可視性を宣言する必要があります( MUST )。

protected または private な可視性を示すために、メソッド名の前に単一のアンダースコア( _ )を付けてはいけません( MUST NOT )。つまり、アンダースコア( _ )のプレフィックスは明示的に意味を持ちません。

メソッド名と関数名は、その後にスペースを入れて宣言してはなりません( MUST NOT )。開き中括弧( { )は独自の行に配置する必要があり( MUST )、閉じ中括弧( } )は本文に続く次の行に配置する必要があります( MUST )。開き丸括弧( ( )の後にスペースがあってはならず( MUST NOT )、閉じ丸括弧( ) )の前にスペースがあってはなりません( MUST NOT )。

メソッド宣言は次のようになります。丸括弧( ( ) )、カンマ、スペース、および中括弧( { } )の配置に注意してください:

<?php
 
namespace Vendor\Package;
 
class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}

関数宣言は次のようになります。丸括弧( ( ) )、カンマ、スペース、および中括弧( { } )の配置に注意してください:

<?php
 
function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
    // function body
}


4.5 メソッドと関数の引数

引数リストでは、各カンマの前にスペースがあってはならず( MUST NOT )、各カンマの後にスペースが1つなければなりません( MUST )。

デフォルト値を持つメソッドと関数の引数は、引数リストの最後に配置する必要があります( MUST )。

<?php
 
namespace Vendor\Package;
 
class ClassName
{
    public function foo(int $arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}

引数リストは複数の行に分割される場合があり( MAY )、後続の各行は1回インデントされます。そうするとき、リストの最初の項目は次の行になければならず( MUST )、1行に1つの引数のみがなければなりません( MUST )。

引数リストが複数の行に分割されている場合、閉じ丸括弧( ) )と開き中括弧( { )は、それらの間に1つのスペースを入れて、同じ行に一緒に配置する必要があります( MUST )。

<?php
 
namespace Vendor\Package;
 
class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // method body
    }
}

戻り値の型宣言が存在する場合、コロンとそれに続く型宣言の間に1つのスペースが必要です( MUST )。コロンと型宣言は、引数リストの閉じ丸括弧( ) )と同じ行になければなりません( MUST )。その時2つの文字( ): )の間にスペースは入れません。

<?php
 
declare(strict_types=1);
 
namespace Vendor\Package;
 
class ReturnTypeVariations
{
    public function functionName(int $arg1, $arg2): string
    {
        return 'foo';
    }
 
    public function anotherFunction(
        string $foo,
        string $bar,
        int $baz
    ): string {
        return 'foo';
    }
}

null許容型宣言では、疑問符( ? )と型の間にスペースがあってはなりません( MUST NOT )。

<?php
 
declare(strict_types=1);
 
namespace Vendor\Package;
 
class ReturnTypeVariations
{
    public function functionName(?string $arg1, ?int &$arg2): ?string
    {
        return 'foo';
    }
}

参照演算子( & )を引数の前に使用する場合、前の例のように、& の後にスペースがあってはなりません( MUST NOT )。

可変長引数の 演算子と引数名の間にスペースがあってはいけません( MUST NOT ):

public function process(string $algorithm, ...$parts)
{
    // processing
}

参照演算子と可変長引数の 演算子の両方を組み合わせる場合、それらの2つの間にスペースがあってはなりません( MUST NOT ):

public function process(string $algorithm, &...$parts)
{
    // processing
}


4.6 abstract, final, and static

abstract 及び final が存在する場合、それらは可視性宣言の前になければなりません( MUST )。

static が存在する場合、それは可視性宣言の後に来なければなりません( MUST )。

<?php
 
namespace Vendor\Package;
 
abstract class ClassName
{
    protected static $foo;
 
    abstract protected function zim();
 
    final public static function bar()
    {
        // method body
    }
}


4.7 メソッドと関数の呼び出し

メソッドまたは関数の呼び出しを行うときは、メソッドまたは関数の名前と開き丸括弧( ( )の間にスペースがあってはならず( MUST NOT )、開き丸括弧( ( )の後にスペースがあってはならず( MUST NOT )、閉じ丸括弧( ) )の前にスペースがあってはなりません( MUST NOT )。引数リストでは、各カンマの前にスペースがあってはならず( MUST NOT )、各カンマの後にスペースが1つなければなりません( MUST )。

<?php
 
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

引数リストは複数の行に分割される場合があり( MAY )、後続の各行は1回インデントされます。そうするとき、リストの最初の項目は次の行になければならず( MUST )、1行に1つの引数のみがなければなりません( MUST )。(無名関数または配列の場合のように)単一の引数が複数行に分割されても、引数リスト自体の分割にはなりません。

<?php
 
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);
<?php
 
somefunction($foo, $bar, [
  // ...
], $baz);
 
$app->get('/hello/{name}', function ($name) use ($app) {
    return 'Hello ' . $app->escape($name);
});


5. 制御構造

制御構造の一般的なスタイル規則は次のとおりです:

各構造の本体は中括弧( { } )で囲む必要があります( MUST )。これにより、構造の外観が標準化され、新しい行が本文に追加されるときにエラーが発生する可能性が低くなります。


5.1 if, elseif, else

if 構造は次のようになります。 丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。そして、elseelseif は前の本体の閉じ中括弧( } )と同じ行にあります。

<?php
 
if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}

すべての制御キーワードが単一の単語のように見えるように、else if の代わりにキーワード elseif を使用すべきです( SHOULD )。

丸括弧( ( ) )内の式は複数の行に分割される場合があり( MAY )、後続の各行は少なくとも1回インデントされます。その場合、最初の条件は次の行になければなりません( MUST )。閉じ丸括弧( ) )と開き中括弧( { )は、それらの間に1つのスペースを入れて、一緒の行に配置する必要があります( MUST )。条件間のブール演算子は、両方の組み合わせではなく、常に行の先頭または末尾になければなりません( MUST )。

<?php
 
if (
    $expr1
    && $expr2
) {
    // if body
} elseif (
    $expr3
    && $expr4
) {
    // elseif body
}


5.2 switch, case

switch の構造は次のようになります。丸括弧( ( ) )、スペース、中括弧( { } )の配置に注意してください。case ステートメントは switch から一回インデントする必要があり( MUST )、break キーワード(または他の終了キーワード)は case 本体と同じレベルでインデントする必要があります( MUST )。空ではないケース本体でフォールスルーが意図的である場合、// no breakなどのコメントが必要です( MUST )。

<?php
 
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}

丸括弧( ( ) )内の式は複数の行に分割される場合があり( MAY )、後続の各行は少なくとも1回インデントされます。その場合、最初の条件は次の行になければなりません( MUST )。閉じ丸括弧( ) )と開き中括弧( { )は、それらの間に1つのスペースを入れて、一緒の行に配置する必要があります( MUST )。条件間のブール演算子は、両方の組み合わせではなく、常に行の先頭または末尾になければなりません( MUST )。

<?php
 
switch (
    $expr1
    && $expr2
) {
    // structure body
}


5.3 while, do while

while ステートメントは次のようになります。丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。

<?php
 
while ($expr) {
    // structure body
}

丸括弧( ( ) )内の式は複数の行に分割される場合があり( MAY )、後続の各行は少なくとも1回インデントされます。その場合、最初の条件は次の行になければなりません( MUST )。閉じ丸括弧( ) )と開き中括弧( { )は、それらの間に1つのスペースを入れて、一緒の行に配置する必要があります( MUST )。条件間のブール演算子は、両方の組み合わせではなく、常に行の先頭または末尾になければなりません( MUST )。

<?php
 
while (
    $expr1
    && $expr2
) {
    // structure body
}

同様に、do while ステートメントは次のようになります。丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。

<?php
 
do {
    // structure body;
} while ($expr);

丸括弧( ( ) )内の式は複数の行に分割される場合があり( MAY )、後続の各行は少なくとも1回インデントされます。その場合、最初の条件は次の行になければなりません( MUST )。条件間のブール演算子は、両方の組み合わせではなく、常に行の先頭または末尾になければなりません( MUST )。

<?php
 
do {
    // structure body;
} while (
    $expr1
    && $expr2
);


5.4 for

for ステートメントは次のようになります。丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。

<?php
 
for ($i = 0; $i < 10; $i++) {
    // for body
}

丸括弧( ( ) )内の式は複数の行に分割される場合があり( MAY )、後続の各行は少なくとも1回インデントされます。その場合、最初の条件は次の行になければなりません( MUST )。閉じ丸括弧( ) )と開き中括弧( { )は、それらの間に1つのスペースを入れて、一緒の行に配置する必要があります( MUST )。

<?php
 
for (
    $i = 0;
    $i < 10;
    $i++
) {
    // for body
}


5.5 foreach

foreach ステートメントは次のようになります。丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。

<?php
 
foreach ($iterable as $key => $value) {
    // foreach body
}


5.6 try, catch, finally

try-catch-finally ブロックは次のようになります。丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。

<?php
 
try {
    // try body
} catch (FirstThrowableType $e) {
    // catch body
} catch (OtherThrowableType | AnotherThrowableType $e) {
    // catch body
} finally {
    // finally body
}


6. オペレーター

演算子のスタイルルールは、アリティ(演算子が取るオペランドの数)ごとにグループ化されています。

演算子の周囲にスペースが許可されている場合、読みやすさの目的で複数のスペースを使用できます( MAY )。

ここで説明されていないすべての演算子は未定義のままです。


6.1. 単項演算子

インクリメント/デクリメント演算子は、演算子とオペランドの間にスペースがあってはいけません( MUST NOT )。

$i++;
++$j;

型キャスト演算子は丸括弧( ( ) )内にスペースがあってはいけません( MUST NOT ):

$intValue = (int) $input;


6.2. 二項演算子

すべての二項演算子(算術演算子、比較演算子、代入演算子、ビット演算子、論理演算子、文字列演算子、および型演算子)の前後には、少なくとも1つのスペースが必要です( MUST ):

if ($a === $b) {
    $foo = $bar ?? $a ?? $b;
} elseif ($a > $b) {
    $foo = $a + $b * $c;
}


6.3. 三項演算子

条件演算子は、単に三項演算子とも呼ばれ、?: の文字の前後に少なくとも1つのスペースがなければなりません( MUST ):

$variable = $foo ? 'foo' : 'bar';

条件演算子の中央のオペランドが省略されている場合、演算子は他の二項比較演算子と同じスタイル規則に従う必要があります( MUST ):

$variable = $foo ?: 'bar';


7. クロージャー

クロージャーは、function キーワードの後にスペースを使用し、use キーワードの前後にスペースを使用して宣言する必要があります( MUST )。

開き中括弧( { )は同じ行に配置する必要があり( MUST )、閉じ中括弧( } )は本文に続く次の行に配置する必要があります( MUST )。

引数リストまたは変数リストの開き丸括弧( ( )の後にスペースがあってはならず( MUST NOT )、引数リストまたは変数リストの閉じ丸括弧( ) )の前にスペースがあってはなりません( MUST NOT )。

引数リストと変数リストでは、各カンマの前にスペースがあってはならず( MUST NOT )、各カンマの後にスペースが1つなければなりません( MUST )。

デフォルト値を持つクロージャー引数は、引数リストの最後に配置する必要があります( MUST )。

戻り値の型が存在する場合、通常の関数とメソッドと同じルールに従う必要があります( MUST )。use キーワードが存在する場合、コロン( : )は、use リストの閉じ丸括弧( ) )の後に続く必要があります( MUST )。その時、2つの文字( ): )の間にスペースは入れません。

クロージャー宣言は次のようになります。丸括弧( ( ) )、スペース、および中括弧( { } )の配置に注意してください。

<?php
 
$closureWithArgs = function ($arg1, $arg2) {
    // body
};
 
$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // body
};
 
$closureWithArgsVarsAndReturn = function ($arg1, $arg2) use ($var1, $var2): bool {
    // body
};

引数リストと変数リストは、複数の行に分割されてもよく( MAY )、後続の各行は1回インデントされます。その場合、リストの最初の項目は次の行になければならず( MUST )、1行に1つの引数または変数のみが存在しなければなりません( MUST )。

最後のリスト(引数または変数に関係なく)が複数の行に分割されている場合、閉じ丸括弧( ) )と開き中括弧( { )は、それらの間に1つのスペースを入れて、同じ行に配置する必要があります( MUST )。

以下は、複数行に分割された引数リストと変数リストがある場合とない場合のクロージャーの例です。

<?php
 
$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // body
};
 
$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};
 
 
$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};
 
$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // body
};
 
$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

クロージャーが関数またはメソッドの呼び出しで引数として直接使用される場合にも、フォーマッティング・ルールが適用されることに注意してください。

<?php
 
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);


8. 匿名クラス

匿名クラスは、上記のセクションのクロージャーと同じガイドラインと原則に従う必要があります( MUST )。

<?php
 
$instance = new class {};

実装インターフェースのリストが折り返されない限り、開き中括弧( { )は class キーワードと同じ行に置くことができます( MAY )。インターフェイスのリストが折り返されている場合、中括弧( ( ) )は最後のインターフェイスの直後の行に配置する必要があります( MUST )。

<?php
 
// Brace on the same line
$instance = new class extends \Foo implements \HandleableInterface {
    // Class content
};
 
// Brace on the next line
$instance = new class extends \Foo implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // Class content
};