一般

PHP タグのオープニングとクローズ

HTML ブロック内に複数行の PHP スニペットを埋め込む場合、PHP のオープンおよびクローズタグはそれぞれ独立した行に配置する必要があります。

正しい (複数行):

  1. function foo() {
  2. ?>
  3. <div>
  4. <?php
  5. echo esc_html(
  6. bar(
  7. $baz,
  8. $bat
  9. )
  10. );
  11. ?>
  12. </div>
  13. <?php
  14. }

正しい (単一行):

  1. <input name="<?php echo esc_attr( $name ); ?>" />

不正:

  1. if ( $a === $b ) { ?>
  2. <some html>
  3. <?php }

ショートハンド PHP タグの使用禁止

重要: ショートハンド PHP スタートタグは決して使用しないでください。常にフル PHP タグを使用してください。

正しい:

  1. <?php ... ?>
  2. <?php echo esc_html( $var ); ?>

不正:

  1. <? ... ?>
  2. <?= esc_html( $var ) ?>

シングルクォートとダブルクォート

適切な場合にシングルクォートとダブルクォートを使用してください。文字列内で何も評価しない場合は、シングルクォートを使用します。文字列内でクォートをエスケープする必要はほとんどありません。なぜなら、クォートスタイルを交互に使用することができるからです。

  1. echo '<a href="/static/link" class="button button-primary">Link name</a>';
  2. echo "<a href='{$escaped_link}'>text with a ' single quote</a>";

HTML または XML 属性に入るテキストは、シングルまたはダブルクォートが属性値を終了させて HTML を無効にし、セキュリティ問題を引き起こさないようにエスケープする必要があります。詳細については、プラグインハンドブックの データ検証 を参照してください。

include/require ステートメントの記述

include[_once]require[_once] は言語構造であるため、パスの周りに括弧を使用する必要はありません。パスと include/require キーワードの間には、1 つのスペースのみが必要です。

無条件のインクルードには require[_once] を使用することを 強く推奨 します。include[_once] を使用すると、ファイルが見つからない場合に PHP が警告を出しますが、実行は続行されます。これは、アプリケーションが読み込まれたファイルに依存している場合、他のエラー/警告/通知が発生する可能性が高く、セキュリティ漏洩につながる可能性があります。そのため、ファイルが見つからない場合に Fatal Error をスローする require[_once] が一般的により良い選択です。

  1. // Correct.
  2. require_once ABSPATH . 'file-name.php';
  3. // Incorrect.
  4. include_once ( ABSPATH . 'file-name.php' );
  5. require_once __DIR__ . '/file-name.php';

命名

命名規則

変数、アクション/フィルター、および関数名には小文字を使用してください (決して camelCase ではありません)。単語はアンダースコアで区切ります。変数名を不必要に省略しないでください。コードは明確で自己文書化されるべきです。

  1. function some_name( $some_variable ) {}

関数パラメータ名については、予約語を名前として使用しないことを強く推奨 します。これは、PHP 8.0 の「関数呼び出しにおける名前付きパラメータ」機能を使用する際に、読みづらく混乱を招くコードにつながるためです。

また、関数パラメータの名前を変更することは、PHP 8.0 以降は破壊的変更と見なされるべきであるため、関数パラメータの名前には十分な注意を払ってください!

クラス、トレイト、インターフェース、および列挙型の名前は、アンダースコアで区切られた大文字の単語を使用する必要があります。略語はすべて大文字であるべきです。

  1. class Walker_Category extends Walker {}
  2. class WP_HTTP {}
  3. interface Mailer_Interface {}
  4. trait Forbid_Dynamic_Properties {}
  5. enum Post_Status {}

定数はすべて大文字で、単語はアンダースコアで区切るべきです:

  1. define( 'DOING_AJAX', true );

ファイル名は小文字を使用して説明的に命名するべきです。ハイフンで単語を区切ります。

  1. my-plugin-name.php

クラスファイル名は、クラス名に class- を前置し、クラス名内のアンダースコアをハイフンに置き換えたものに基づくべきです。たとえば、WP_Error は次のようになります:

  1. class-wp-error.php

このファイル命名基準は、テストクラスを除くすべての現在および新しいファイルに適用されます。

テストクラスを含むファイルの名前は、PSR4 に従ってクラス名を正確に反映する必要があります。これは、すべてのサポートされている PHPUnit バージョンとの互換性を確保するためです [https://github.com/sebastianbergmann/phpunit/pull/4109]。

wp-includes ディレクトリ内のテンプレートタグを含むファイルは、-template を名前の末尾に追加して明確にする必要があります。

  1. general-template.php

動的フックの命名のための補間

動的フックは、可読性と発見性の目的のために、連結ではなく補間を使用して命名するべきです。

動的フックは、タグ名に動的値を含むフックです。例: {$new_status}_{$post->post_type} (publish_post)。

フックタグで使用される変数は、波括弧 {} で囲む必要があり、完全な外部タグ名は二重引用符で囲む必要があります。これは、PHP が補間された文字列内の変数の型を正しく解析できるようにするためです。

  1. do_action( "{$new_status}_{$post->post_type}", $post->ID, $post );

可能な限り、タグ名内の動的値は簡潔であるべきです。$user_id は、たとえば $this->id よりも自己文書化されています。

ホワイトスペース

スペースの使用

常にカンマの後、論理、算術、比較、文字列、および代入演算子の両側にスペースを入れてください。

  1. SOME_CONST === 23;
  2. foo() && bar();
  3. ! $foo;
  4. array( 1, 2, 3 );
  5. $baz . '-5';
  6. $term .= 'X';
  7. if ( $object instanceof Post_Type_Interface ) {}
  8. $result = 2 ** 3; // 8.

制御構造ブロックの開き括弧と閉じ括弧の両側にスペースを入れてください。

  1. foreach ( $foo as $bar ) { ...

関数を定義する場合は、次のようにしてください:

  1. function my_function( $param1 = 'foo', $param2 = 'bar' ) { ...
  2. function my_other_function() { ...

関数を呼び出す場合は、次のようにしてください:

  1. my_function( $param1, func_param( $param2 ) );
  2. my_other_function();

論理比較を行う場合は、次のようにしてください:

  1. if ( ! $foo ) { ...

型キャスト は小文字でなければなりません。常に型キャストの短い形式を優先してください。(int) の代わりに (integer)(bool) の方が良いです。浮動小数点キャストには (float) を使用し、(real) は PHP 7.4 で 非推奨 となり、PHP 8 で削除されました:

  1. foreach ( (array) $foo as $bar ) { ...
  2. $foo = (bool) $bar;

配列アイテムを参照する場合、インデックスが変数である場合のみ、周囲にスペースを含める必要があります。たとえば:

  1. $x = $foo['bar']; // Correct.
  2. $x = $foo[ 'bar' ]; // Incorrect.
  3. $x = $foo[0]; // Correct.
  4. $x = $foo[ 0 ]; // Incorrect.
  5. $x = $foo[ $bar ]; // Correct.
  6. $x = $foo[$bar]; // Incorrect.

switch ブロック内では、case 条件とコロンの間にスペースを入れてはいけません。

  1. switch ( $foo ) {
  2. case 'bar': // Correct.
  3. case 'ba' : // Incorrect.
  4. }

特に指定がない限り、括弧内にはスペースを入れるべきです。

  1. if ( $foo && ( $bar || $baz ) ) { ...
  2. my_function( ( $x - 1 ) * 5, $y );

インクリメント (++) またはデクリメント (--) 演算子を使用する場合、演算子とそれが適用される変数の間にスペースを入れてはいけません。

  1. // Correct.
  2. for ( $i = 0; $i < 10; $i++ ) {}
  3. // Incorrect.
  4. for ( $i = 0; $i < 10; $i ++ ) {}
  5. ++ $b; // Multiple spaces.

インデント

インデントは常に論理構造を反映するべきです。実際のタブを使用し、スペースではなく、これによりクライアント間で最大の柔軟性が得られます。

例外: コードのブロックが整列されている方が読みやすい場合は、スペースを使用してください:

  1. [tab]$foo = 'somevalue';
  2. [tab]$foo2 = 'somevalue2';
  3. [tab]$foo34 = 'somevalue3';
  4. [tab]$foo5 = 'somevalue4';

連想配列の場合、各アイテム は、配列が 1 つ以上のアイテムを含む場合に新しい行で始まるべきです:

  1. $query = new WP_Query( array( 'ID' => 123 ) );
  1. $args = array(
  2. [tab]'post_type' => 'page',
  3. [tab]'post_author' => 123,
  4. [tab]'post_status' => 'publish',
  5. );
  6. $query = new WP_Query( $args );

最後の配列アイテムの後のカンマに注意してください: これは、配列の順序を変更しやすくし、新しいアイテムが追加されたときのクリーンな差分を作成するために推奨されます。

  1. $my_array = array(
  2. [tab]'foo' => 'somevalue',
  3. [tab]'foo2' => 'somevalue2',
  4. [tab]'foo3' => 'somevalue3',
  5. [tab]'foo34' => 'somevalue3',
  6. );

switch 制御構造の場合、case ステートメントは switch ステートメントから 1 タブ分インデントされ、case の内容は case 条件ステートメントから 1 タブ分インデントされるべきです。

  1. switch ( $type ) {
  2. [tab]case 'foo':
  3. [tab][tab]some_function();
  4. [tab][tab]break;
  5. [tab]case 'bar':
  6. [tab][tab]some_function();
  7. [tab][tab]break;
  8. }

目安: インデントには行の先頭にタブを使用し、整列には中間行でスペースを使用できます。

トレーリングスペースの削除

各行の末尾にトレーリングホワイトスペースを削除してください。ファイルの末尾に閉じる PHP タグを省略することが推奨されます。タグを使用する場合は、トレーリングホワイトスペースを削除してください。

関数本体の末尾にトレーリング空白行があってはいけません。

フォーマット

ブレーススタイル

ブレースは、ここに示すスタイルで全てのブロックに使用されるべきです:

  1. if ( condition ) {
  2. action1();
  3. action2();
  4. } elseif ( condition2 && condition3 ) {
  5. action3();
  6. action4();
  7. } else {
  8. defaultaction();
  9. }

非常に長いブロックがある場合は、複雑さを減らし、テストの容易さを改善し、可読性を向上させるために、2 つ以上の短いブロック、関数、またはメソッドに分割できるかどうかを検討してください。

ブレースは常に使用されるべきであり、必要ない場合でも使用されるべきです:

  1. if ( condition ) {
  2. action0();
  3. }
  4. if ( condition ) {
  5. action1();
  6. } elseif ( condition2 ) {
  7. action2a();
  8. action2b();
  9. }
  10. foreach ( $items as $item ) {
  11. process_item( $item );
  12. }

ブレースの使用を要求することは、単一ステートメントのインライン制御構造 を禁止することを意味します。制御構造の 代替構文 (例: if/endifwhile/endwhile) を自由に使用できます。特に PHP コードが HTML 内に埋め込まれているテンプレートでは、次のように:

  1. <?php if ( have_posts() ) : ?>
  2. <div class="hfeed">
  3. <?php while ( have_posts() ) : the_post(); ?>
  4. <article id="<?php echo esc_attr( 'post-' . get_the_ID() ); ?>" class="<?php echo esc_attr( get_post_class() ); ?>">
  5. <!-- ... -->
  6. </article>
  7. <?php endwhile; ?>
  8. </div>
  9. <?php endif; ?>

配列の宣言

配列を宣言するために長い配列構文 ( array( 1, 2, 3 ) ) を使用することは、短い配列構文 ( [ 1, 2, 3 ] ) よりも一般的に読みやすいです。特に視覚的に困難を抱えている人にとっては、初心者にとってもはるかに説明的です。

配列は長い配列構文を使用して宣言する必要があります。

複数行の関数呼び出し

関数呼び出しを複数行に分割する場合、各パラメータは別の行に配置する必要があります。単一行のインラインコメントは独自の行を取ることができます。

各パラメータは 1 行を超えてはなりません。複数行のパラメータ値は変数に割り当て、その変数を関数呼び出しに渡す必要があります。

  1. $bar = array(
  2. 'use_this' => true,
  3. 'meta_key' => 'field_name',
  4. );
  5. $baz = sprintf(
  6. /* translators: %s: Friend's name */
  7. __( 'Hello, %s!', 'yourtextdomain' ),
  8. $friend_name
  9. );
  10. $a = foo(
  11. $bar,
  12. $baz,
  13. /* translators: %s: cat */
  14. sprintf( __( 'The best pet is a %s.' ), 'cat' )
  15. );

型宣言

型宣言の前後には正確に 1 つのスペースが必要です。nullability 演算子 (?) は型宣言の一部と見なされ、この演算子と実際の型の間にスペースを入れてはいけません。クラス/インターフェース/列挙型名に基づく型宣言は、宣言されたクラス/インターフェース/列挙型名のケースを使用する必要がありますが、キーワードベースの型宣言は小文字にする必要があります。

戻り値の型宣言は、関数宣言の閉じ括弧と戻り値の型を開始するコロンの間にスペースを入れてはいけません。

これらのルールは、型宣言を許可するすべての構造に適用されます: 関数、クロージャ、列挙型、キャッチ条件、PHP 7.4 の矢印関数および型付きプロパティも含まれます。

  1. // Correct.
  2. function foo( Class_Name $parameter, callable $callable, int $number_of_things = 0 ) {
  3. // Do something.
  4. }
  5. function bar(
  6. Interface_Name&Concrete_Class $param_a,
  7. string|int $param_b,
  8. callable $param_c = 'default_callable'
  9. ): User|false {
  10. // Do something.
  11. }
  12. // Incorrect.
  13. function baz(Class_Name $param_a, String$param_b, CALLABLE $param_c ) : ? iterable {
  14. // Do something.
  15. }

型宣言の使用には、アプリケーションの最小 PHP バージョンに基づく以下の制限があります。これは WordPress コア、プラグイン、またはテーマに関係します:

  • スカラー boolintfloat、および string 型宣言は、最小 PHP バージョンが PHP 7.0 以上でないと使用できません。
  • 戻り値の型宣言は、最小 PHP バージョンが PHP 7.0 以上でないと使用できません。
  • nullable 型宣言は、最小 PHP バージョンが PHP 7.1 以上でないと使用できません。
  • iterable および void 型宣言は、最小 PHP バージョンが PHP 7.1 以上でないと使用できません。void 型は戻り値の型としてのみ使用できます。
  • object 型宣言は、最小 PHP バージョンが PHP 7.2 以上でないと使用できません。
  • プロパティ型宣言は、最小 PHP バージョンが PHP 7.4 以上でないと使用できません。
  • static (戻り値の型のみ) は、最小 PHP バージョンが PHP 8.0 以上でないと使用できません。
  • mixed 型は、最小 PHP バージョンが PHP 8.0 以上でないと使用できません。mixed 型には null が含まれるため、nullable にすることはできません。
  • ユニオン型は、最小 PHP バージョンが PHP 8.0 以上でないと使用できません。
  • インターセクション型は、最小 PHP バージョンが PHP 8.1 以上でないと使用できません。
  • never (戻り値の型のみ) は、最小 PHP バージョンが PHP 8.1 以上でないと使用できません。
  • 排他的正規形型 (ユニオン型とインターセクション型を組み合わせたもの) は、最小 PHP バージョンが PHP 8.2 以上でないと使用できません。

WordPress コアでの使用

既存の WordPress コア関数に型宣言を追加することは、非常に注意して行うべきです。

プラグインやテーマによってオーバーロード可能な関数 (メソッド) の関数シグネチャには手を加えないでください。

これにより、今のところ、型宣言を追加する候補として、グローバル名前空間の無条件で宣言された関数、private クラスメソッド、およびコアに新しいコードのみが残ります。

注意: 型宣言で array キーワードを使用することは、現在は強く推奨されません。なぜなら、実装の柔軟性を高めるために iterable を使用する方が良い場合が多く、そのキーワードはまだ WordPress コアで使用できるようにするための最小要件が引き上げられていないからです。

マジック定数

PHP ネイティブ * マジック定数CLASSDIR のようなものは、使用する際には大文字で書くべきです。

クラス名解決のために ::class 定数を使用する場合、class キーワードは小文字であり、:: 演算子の周りにスペースを入れてはいけません。

  1. // Correct.
  2. add_action( 'action_name', array( __CLASS__, 'method_name' ) );
  3. add_action( 'action_name', array( My_Class::class, 'method_name' ) );
  4. // Incorrect.
  5. require_once __dIr__ . '/relative-path/file-name.php';
  6. add_action( 'action_name', array( My_Class :: CLASS, 'method_name' ) );

スプレッド演算子 …

スプレッド演算子を使用する場合、スプレッド演算子の前に 1 つのスペースまたは適切なインデントを持つ新しい行が必要です。スプレッド演算子とそれが適用される変数/関数呼び出しの間にはスペースを入れてはいけません。スプレッド演算子と参照演算子 (&) を組み合わせる場合、間にスペースを入れてはいけません。

  1. // Correct.
  2. function foo( &...$spread ) {
  3. bar( ...$spread );
  4. bar(
  5. array( ...$foo ),
  6. ...array_values( $keyed_array )
  7. );
  8. }
  9. // Incorrect.
  10. function fool( & ... $spread ) {
  11. bar(...
  12. $spread );
  13. bar(
  14. [... $foo ],... array_values( $keyed_array )
  15. );
  16. }

スプレッド演算子 (他の言語ではスプラット演算子として知られています) は、関数宣言 (可変長関数) で引数をパッキングし、関数呼び出しでアンパッキングするために PHP 5.6 以降で使用できます。PHP 7.4 以降、スプレッド演算子は数値インデックス配列のアンパッキングにも使用され、PHP 8.1 以降は文字列キー付き配列のアンパッキングが可能です。

関数宣言で使用される場合、スプレッド演算子は最後のパラメータでのみ使用できます。

宣言ステートメント、名前空間、およびインポートステートメント

名前空間の宣言

名前空間名の各部分は、アンダースコアで区切られた大文字の単語で構成されるべきです。

名前空間の宣言の前には正確に 1 行の空白行が必要で、後にも少なくとも 1 行の空白行が必要です。

  1. namespace Prefix\Admin\Domain_URL\Sub_Domain\Event; // Correct.

ファイルごとに名前空間の宣言は 1 つだけで、ファイルの先頭に配置する必要があります。波括弧構文を使用した名前空間の宣言は許可されていません。明示的なグローバル名前空間の宣言 (名前なしの名前空間宣言) も許可されていません。

  1. // Incorrect: namespace declaration using curly brace syntax.
  2. namespace Foo {
  3. // Code.
  4. }
  5. // Incorrect: namespace declaration for the global namespace.
  6. namespace {
  7. // Code.
  8. }

WordPress コアに名前空間を導入するタイムラインは現在ありません。

プラグインやテーマでの名前空間の使用は強く推奨されます。これは、他のプラグイン、テーマ、および/または WordPress コアとの名前の衝突を防ぐために、コードの多くにプレフィックスを付ける素晴らしい方法です。

実際に衝突を防ぐために、ユニークで十分に長い名前空間プレフィックスを使用することを確認してください。一般的に、Vendor\Project_Name のような名前空間プレフィックスを使用することは良いアイデアです。

wp および WordPress 名前空間プレフィックスは WordPress 自体に予約されています。

名前空間は、define() で宣言された変数、定数、または非 PHP ネイティブ構造 (WordPress で使用されるフック名など) には影響しません。

これらは依然として個別にプレフィックスを付ける必要があります。

インポート use ステートメントの使用

インポート use ステートメントを使用すると、現在の名前空間の外にある定数、関数、クラス、インターフェース、名前空間、列挙型、およびトレイトを参照できます。

インポート use ステートメントはファイルの先頭に配置し、(オプションの) namespace 宣言に続けるべきです。インポートのタイプに基づいて特定の順序に従う必要があります:

  • 1. use ステートメント (名前空間、クラス、インターフェース、トレイト、列挙型)
  • 2. use ステートメント (関数)
  • 3. use ステートメント (定数)

エイリアスを使用して名前の衝突を防ぐことができます (異なる名前空間で同じクラス名を持つ 2 つのクラス)。

エイリアスを使用する場合は、エイリアスが WordPress の命名規則に従い、ユニークであることを確認してください。

以下の例は、スペース、グルーピング、先頭のバックスラッシュなどに関するインポート use ステートメントの正しい使用法と誤った使用法を示しています。

正しい:

  1. namespace Project_Name\Feature;
  2. use Project_Name\Sub_Feature\Class_A;
  3. use Project_Name\Sub_Feature\Class_C as Aliased_Class_C;
  4. use Project_Name\Sub_Feature\{
  5. Class_D,
  6. Class_E as Aliased_Class_E,
  7. }
  8. use function Project_Name\Sub_Feature\function_a;
  9. use function Project_Name\Sub_Feature\function_b as aliased_function;
  10. use const Project_Name\Sub_Feature\CONSTANT_A;
  11. use const Project_Name\Sub_Feature\CONSTANT_D as ALIASED_CONSTANT;
  12. // Rest of the code.

不正:

  1. namespace Project_Name\Feature;
  2. use const Project_Name\Sub_Feature\CONSTANT_A; // Superfluous whitespace after the "use" and the "const" keywords.
  3. use function Project_Name\Sub_Feature\function_a; // Function import after constant import.
  4. use \Project_Name\Sub_Feature\Class_C as aliased_class_c; // Leading backslash shouldn't be used, alias doesn't comply with naming conventions.
  5. use Project_Name\Sub_Feature\{Class_D, Class_E as Aliased_Class_E} // Extra spaces around the "as" keyword, incorrect whitespace use inside the brace opener and closer.
  6. use Vendor\Package\{ function function_a, function function_b,
  7. Class_C,
  8. const CONSTANT_NAME}; // Combining different types of imports in one use statement, incorrect whitespace use within group use statement.
  9. class Foo {
  10. // Code.
  11. }
  12. use const \Project_Name\Sub_Feature\CONSTANT_D as Aliased_constant; // Import after class definition, leading backslash, naming conventions violation.
  13. use function Project_Name\Sub_Feature\function_b as Aliased_Function; // Import after class definition, naming conventions violation.
  14. // Rest of the code.

インポート use ステートメントは、動的クラス、関数、または定数名には影響しません。

グループ use ステートメントは PHP 7.0 から利用可能で、グループ use ステートメントのトレーリングカンマは PHP 7.2 から利用可能です。

注意: オートローディング を実装していない限り、use ステートメントは自動的にインポートされるものをロードしません。オートローディングを設定するか、インポートされた構造が使用されるときにクラス/関数/定数を含むファイルを require/import ステートメントを使用してロードする必要があります。

WordPress コアでの使用に関する注意

インポート use ステートメントはすでに WordPress コアで使用できますが、現時点では強く推奨されません

インポート use ステートメントは、名前空間とクラスのオートローディング実装と組み合わせると最も便利です。

これらのいずれも現在 WordPress コアには存在せず、これに関する議論が進行中であるため、WordPress コアにインポート use ステートメントを追加するのは今のところ賢明な選択です。

オブジェクト指向プログラミング

ファイルごとに 1 つのオブジェクト構造 (クラス/インターフェース/トレイト/列挙型) のみ

たとえば、class-example-class.php というファイルがある場合、そのファイルには 1 つのクラスしか含めることができません。

  1. // Incorrect: file class-example-class.php.
  2. class Example_Class {}
  3. class Example_Class_Extended {}

2 番目のクラスは、class-example-class-extended.php という独自のファイルに配置する必要があります。

  1. // Correct: file class-example-class.php.
  2. class Example_Class {}
  1. // Correct: file class-example-class-extended.php.
  2. class Example_Class_Extended {}

トレイト使用ステートメント

トレイト use ステートメントはクラスの先頭に配置し、最初の use ステートメントの前に正確に 1 行の空白行を持ち、最後のステートメントの後にも少なくとも 1 行の空白行を持つべきです。クラスがトレイト use ステートメントのみを含む場合は、後の空白行を省略できます。

以下のコード例は、トレイト use ステートメントに関するフォーマット要件を示しています。スペース、グルーピング、インデントなどに関するものです。

  1. // Correct.
  2. class Foo {
  3. use Bar_Trait;
  4. use Foo_Trait,
  5. Bazinga_Trait {
  6. Bar_Trait::method_name insteadof Bar_Trait;
  7. Bazinga_Trait::method_name as bazinga_method;
  8. }
  9. use Loopy_Trait {
  10. eat as protected;
  11. }
  12. public $baz = true;
  13. ...
  14. }
  15. // Incorrect.
  16. class Foo {
  17. // No blank line before trait use statement, multiple spaces after the use keyword.
  18. use Bar_Trait;
  19. /*
  20. * Multiple spaces when importing traits, no new line after opening brace.
  21. * Aliasing should be done on the same line as the method it's replacing.
  22. */
  23. use Foo_Trait, Bazinga_Trait{Bar_Trait::method_name insteadof Foo_Trait; Bazinga_Trait::method_name
  24. as bazinga_method;
  25. }; // Wrongly indented brace.
  26. public $baz = true; // Missing blank line after trait import.
  27. ...
  28. }

可視性は常に宣言されるべき

それを許可するすべての構造 (プロパティ、メソッド、PHP 7.1 以降のクラス定数) について、可視性は明示的に宣言されるべきです。

プロパティ宣言に var キーワードを使用することは許可されていません。

  1. // Correct.
  2. class Foo {
  3. public $foo;
  4. protected function bar() {}
  5. }
  6. // Incorrect.
  7. class Foo {
  8. var $foo;
  9. function bar() {}
  10. }

WordPress コアでの使用

クラス定数の可視性は、最小 PHP バージョンが PHP 7.1 に引き上げられるまで WordPress コアでは使用できません。

可視性と修飾子の順序

クラス宣言に複数の修飾子を使用する場合、順序は次のようにするべきです:

  • 1. 最初にオプションの abstract または final 修飾子。
  • 2. 次にオプションの readonly 修飾子。

オブジェクト指向構造内の定数宣言に複数の修飾子を使用する場合、順序は次のようにするべきです:

  • 1. 最初にオプションの final 修飾子。
  • 2. 次に可視性修飾子。

プロパティ宣言に複数の修飾子を使用する場合、順序は次のようにするべきです:

  • 1. 最初に可視性修飾子。
  • 2. 次にオプションの static または readonly 修飾子 (これらのキーワードは相互に排他的です)。
  • 3. 最後にオプションの type 宣言。

メソッド宣言に複数の修飾子を使用する場合、順序は次のようにするべきです:

  • 1. 最初にオプションの abstract または final 修飾子。
  • 2. 次に可視性修飾子。
  • 3. 最後にオプションの static 修飾子。
  1. // Correct.
  2. abstract readonly class Foo {
  3. private const LABEL = 'Book';
  4. public static $foo;
  5. private readonly string $bar;
  6. abstract protected static function bar();
  7. }
  8. // Incorrect.
  9. class Foo {
  10. protected final const SLUG = 'book';
  11. static public $foo;
  12. static protected final function bar() {
  13. // Code.
  14. };
  15. }

– OO 定数の可視性は PHP 7.1 以降に宣言できます。

– 型付きプロパティは PHP 7.4 以降に利用可能です。

– 読み取り専用プロパティは PHP 8.1 以降に利用可能です。

final 修飾子は PHP 8.1 以降にオブジェクト指向構造の定数に対して利用可能です。

– 読み取り専用クラスは PHP 8.2 以降に利用可能です。

オブジェクトのインスタンス化

新しいオブジェクトインスタンスをインスタンス化する際には、常に括弧を使用する必要があります。厳密に必要でない場合でもです。

インスタンス化されるクラスの名前と開き括弧の間にスペースを入れてはいけません。

  1. // Correct.
  2. $foo = new Foo();
  3. $anonymous_class = new class( $parameter ) { ... };
  4. $instance = new static();
  5. // Incorrect.
  6. $foo = new Foo;
  7. $anonymous_class = new class ( $input ) { ... };

制御構造

else if ではなく elseif を使用

else ifif|elseif ブロックのコロン構文と互換性がありません。このため、条件文には elseif を使用してください。

ヨーダ条件

  1. if ( true === $the_force ) {
  2. $victorious = you_will( $be );
  3. }

変数を含む論理比較を行う場合は、常に変数を右側に置き、定数、リテラル、または関数呼び出しを左側に置いてください。どちらの側も変数でない場合、順序は重要ではありません。(コンピュータサイエンス用語で言えば [https://en.wikipedia.org/wiki/Value_(computer_science]#Assignment:_l-values_and_r-values)、比較では常に l 値を右側に、r 値を左側に置くようにしてください。

上記の例では、等号を省略すると (認めますが、最も経験豊富な私たちにも起こります)、定数 true に代入することはできないため、構文エラーが発生します。もし文が逆で ( $the_force = true ) であった場合、代入は完全に有効で、1 を返し、if 文が true になるため、そのバグを追いかけるのに時間がかかるかもしれません。

少し奇妙に感じるかもしれませんが、慣れてください。

これは ==!====、および !== にも適用されます。<><=、または >= のヨーダ条件は、読みづらく、避けるべきです。

演算子

三項演算子

三項演算子 は問題ありませんが、常に文が真であるかどうかをテストするようにしてください。そうでないと、混乱を招きます。(例外は ! empty() を使用する場合で、ここで false をテストすることは一般的により直感的です。)

短い三項演算子は使用してはいけません。

たとえば:

  1. // (if statement is true) ? (do this) : (else, do this);
  2. $musictype = ( 'jazz' === $music ) ? 'cool' : 'blah';
  3. // (if field is not empty ) ? (do this) : (else, do this);

エラー制御演算子 @

PHP ドキュメント に記載されているように:

PHP は 1 つのエラー制御演算子をサポートしています: アットマーク (@)。PHP の式の前に付けると、その式によって生成される可能性のある診断エラーは抑制されます。
この演算子はコアに存在しますが、適切なエラーチェックを行う代わりに怠惰に使用されることがよくあります。その使用は強く推奨されません。PHP ドキュメントでも次のように述べています:
警告: PHP 8.0.0 より前は、@ 演算子がスクリプトの実行を終了させる重大なエラーを無効にすることが可能でした。たとえば、存在しない関数の呼び出しの前に @ を付けると、スクリプトは理由を示さずに終了します。

インクリメント/デクリメント演算子

前置インクリメント/デクリメントは、スタンドアロンステートメントに対して後置インクリメント/デクリメントよりも好まれるべきです。

前置インクリメント/デクリメントはインクリメント/デクリメントを行い、その後返しますが、後置インクリメント/デクリメントは返してからインクリメント/デクリメントを行います。

「前置」バージョンを使用することはわずかにパフォーマンスが向上し、コードが移動されたときに将来のバグを防ぐことができます。

  1. // Correct: Pre-decrement.
  2. --$a;
  3. // Incorrect: Post-decrement.
  4. $a--;

データベース

データベースクエリ

データベースに直接触れることは避けてください。必要なデータを取得できる定義済みの関数がある場合は、それを使用してください。データベースの抽象化 (クエリの代わりに関数を使用すること) は、コードを将来の互換性を保つのに役立ち、結果がメモリにキャッシュされている場合は、何倍も速くなることがあります。

データベースに触れる必要がある場合は、Trac チケットを作成することを検討してください。そこで、将来の WordPress バージョンに必要な機能をカバーする新しい関数を追加する可能性について議論できます。

SQL ステートメントのフォーマット

SQL ステートメントをフォーマットする際は、十分に複雑な場合は複数行に分けてインデントすることができます。ただし、ほとんどのステートメントは 1 行でうまく機能します。SQL の部分 (例: UPDATEWHERE) は常に大文字にしてください。

データベースを更新する関数は、渡されるパラメータに SQL スラッシュエスケープがないことを期待する必要があります。エスケープは、クエリの実行時にできるだけ近くで行うべきで、$wpdb->prepare() を使用するのが望ましいです。

$wpdb->prepare() は、SQL クエリのエスケープ、引用、および整数キャストを処理するメソッドです。sprintf() スタイルのフォーマットのサブセットを使用します。例:

  1. $var = "dangerous'"; // Raw data that may or may not need to be escaped.
  2. $id = some_foo_number(); // Data we expect to be an integer, but we're not certain.
  3. $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $var, $id ) );

クエリ文字列内で使用できるプレースホルダーは次のとおりです:

  • %d (整数)
  • %f (浮動小数点)
  • %s (文字列)
  • %i (識別子、例: テーブル/フィールド名)

これらのプレースホルダーは「引用」されるべきではありません! $wpdb->prepare() がエスケープと引用を処理します。これにより、何かがエスケープされているかどうかを一目で確認できるようになります。なぜなら、それはクエリが実行されるときに行われるからです。

詳細については、プラグインハンドブックの データ検証 を参照してください。

推奨事項

関数引数の自己説明的フラグ値

関数を呼び出すときは、truefalse ではなく、文字列値を好んで使用してください。

  1. // Incorrect.
  2. function eat( $what, $slowly = true ) {
  3. ...
  4. }
  5. eat( 'mushrooms' );
  6. eat( 'mushrooms', true ); // What does true mean?
  7. eat( 'dogfood', false ); // What does false mean? The opposite of true?

PHP は PHP 8.0 以降にのみ名前付き引数をサポートします。ただし、WordPress は現在も古い PHP バージョンをサポートしているため、まだそれを使用することはできません。

名前付き引数がない場合、フラグの値は無意味であり、上記のような関数呼び出しに出くわすたびに、関数定義を探さなければなりません。コードは、ブール値の代わりに説明的な文字列値を使用することで、より読みやすくなります。

  1. // Correct.
  2. function eat( $what, $speed = 'slowly' ) {
  3. ...
  4. }
  5. eat( 'mushrooms' );
  6. eat( 'mushrooms', 'slowly' );
  7. eat( 'dogfood', 'quickly' );

関数パラメータを説明するためにより多くの単語が必要な場合、$args 配列がより良いパターンかもしれません。

  1. function eat( $what, $args ) {
  2. ...
  3. }
  4. eat ( 'noodles', array( 'speed' => 'moderate' ) );

このパターンを使用する際は注意が必要です。入力が使用前に検証されていない場合、「未定義の配列インデックス」通知が発生する可能性があります。このパターンは、意味がある場合 (すなわち、複数の可能な引数) のみ使用してください。単にそのためだけに使用しないでください。

巧妙なコード

一般的に、可読性は巧妙さや簡潔さよりも重要です。

  1. isset( $var ) || $var = some_function();

上記の行は巧妙ですが、慣れていないと理解するのに時間がかかります。だから、次のように書いてください:

  1. if ( ! isset( $var ) ) {
  2. $var = some_function();
  3. }

絶対に必要でない限り、緩やかな比較は使用しないでください。その動作は誤解を招く可能性があります。

正しい:

  1. if ( 0 === strpos( $text, 'WordPress' ) ) {
  2. echo esc_html__( 'Yay WordPress!', 'textdomain' );
  3. }

不正:

  1. if ( 0 == strpos( 'WordPress', 'foo' ) ) {
  2. echo esc_html__( 'Yay WordPress!', 'textdomain' );
  3. }

代入は条件文に配置してはいけません。

正しい:

  1. $data = $wpdb->get_var( '...' );
  2. if ( $data ) {
  3. // Use $data.
  4. }

不正:

  1. if ( $data = $wpdb->get_var( '...' ) ) {
  2. // Use $data.
  3. }

switch ステートメントでは、複数の空のケースが共通のブロックにフォールスルーするのは問題ありません。ただし、ケースがブロックを含み、次のブロックにフォールスルーする場合は、明示的にコメントを付ける必要があります。

  1. switch ( $foo ) {
  2. case 'bar': // Correct, an empty case can fall through without comment.
  3. case 'baz':
  4. echo esc_html( $foo ); // Incorrect, a case with a block must break, return, or have a comment.
  5. case 'cat':
  6. echo 'mouse';
  7. break; // Correct, a case with a break does not require a comment.
  8. case 'dog':
  9. echo 'horse';
  10. // no break // Correct, a case can have a comment to explicitly mention the fall through.
  11. case 'fish':
  12. echo 'bird';
  13. break;
  14. }

goto ステートメントは決して使用してはいけません。

eval() 構造は非常に危険であり、安全にすることは不可能です。さらに、create_function() 関数は、内部で eval() を実行し、PHP 7.2 以降は非推奨となり、PHP 8.0 で削除されました。これらのいずれも使用してはいけません。

クロージャ(匿名関数)

適切な場合、クロージャはコールバックとして渡す新しい関数を作成する代替手段として使用できます。例えば:

  1. $caption = preg_replace_callback(
  2. '/<[a-zA-Z0-9]+(?: [^<>]+>)*/',
  3. function ( $matches ) {
  4. return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] );
  5. },
  6. $caption
  7. );

クロージャはフィルターやアクションのコールバックとして渡すべきではありません。remove_action() / remove_filter() を介してこれらを削除するのは複雑です(現時点では)(これに対処する提案については #46635 を参照してください)。

正規表現

Perl 互換の正規表現(PCREpreg_ 関数)は、POSIX の対応物よりも優先して使用するべきです。/e スイッチは決して使用せず、preg_replace_callback を代わりに使用してください。

正規表現には、ダブルクォートの文字列とは異なり、エスケープが必要なメタシーケンスが2つだけあるため、シングルクォートの文字列を使用するのが最も便利です: \'\\

extract()を使用しない

Per #22400:

extract() は、コードのデバッグを難しくし、理解を困難にするひどい関数です。私たちはその使用を控えるべきであり、すべての使用を削除するべきです。
Joseph Scott は なぜそれが悪いのかについての良い解説 をしています。

シェルコマンド

バックティック演算子 の使用は許可されていません。

バックティック演算子の使用は shell_exec() と同じであり、ほとんどのホストはセキュリティ上の理由から php.ini ファイルでこの機能を無効にしています。