PHP コーディング規約

PHP コーディング規約は、WordPress コミュニティ全体を対象としています。規約の遵守は WordPress コアでは必須、テーマやプラグインでも同様に使用を推奨します。

テーマやプラグインは別の コーディングスタイル を選択できますが、この コーディング規約 は、単なる コーディングスタイル ではなく、WordPress エコシステムの相互運用性、翻訳、セキュリティに関する確立したベストプラクティスを包含するものです。別の コーディングスタイル を使用する場合でも、このベストプラクティスに関しては WordPress コーディング規約を遵守することを推奨します。

すべてのコードは、(まだ) この規約に完全に準拠していませんが、新しくコミットされたコードや更新されたコードは、コーディング規約に完全に準拠する必要があります。

また、PHP インラインドキュメント規約も参照してください。

この規約への準拠を自動的にチェックしたい場合は、PHP_CodeSniffer を使用して実行する公式の WordPress Coding Standards ツールを使用してください。

全般

開始、終了の PHP タグ

HTML ブロック内に複数行の PHP コードを埋め込む場合、PHP 開始タグ、終了タグはそれぞれ1行を使用してください。

正しい (複数行):

function foo() {
    ?>
    <div>
        <?php
        echo esc_html(
            bar(
                $baz,
                $bat
            )
        );
        ?>
    </div>
    <?php
}

正しい (単一行):

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

間違い:

if ( $a === $b ) { ?>
<some html>
<?php }

PHP ショートタグは禁止

重要 絶対に PHP のショートタグは使わないでください。常に完全な PHP タグを使用してください。

正しい:

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

間違い:

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

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

シングルクォートとダブルクォートは適切に使い分けてください。文字列の中で何も評価しない場合は、シングルクォートを使用してください。クォートの種類を入れ替えれば済むため、文字列の中でエスケープを使用する必要はほとんどないはずです。

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

HTML や XML の属性に入るテキストはエスケープしてください。シングルクォートまたはダブルクォートが閉じていない属性値は、HTML として無効で、セキュリティ問題を引き起こす可能性があります。詳細については、プラグインハンドブックの Data Validation を参照してください。

include 文、require 文の記述

include[_once] と require[_once] は言語構成要素のため、パスを括弧で囲む必要はありません。パスと include キーワード、require キーワードの間には、スペースを1つだけ挿入してください。

無条件のインクルードには require[_once] を使用することを 強く推奨 します。include[_once] を使用すると、PHP はファイルが見つからなければ警告を投げますが、処理は続行します。アプリケーションが読み込むファイルに依存する場合、ほぼ間違いなく他のエラー、警告、通知がスローされ、潜在的にはセキュリティリークにつながります。そのため、一般には require[_once] の方が良い選択です。ファイルが見つからなければ Fatal Error がスローされます。

// 正しい
require_once ABSPATH . 'file-name.php';

// 間違い
include_once  ( ABSPATH . 'file-name.php' );
require_once     __DIR__ . '/file-name.php';

命名

命名規則

変数、アクション、関数の名前にはアルファベット小文字を使います。camelCase は使いません。単語はアンダースコアで区切ります。不必要に変数名を省略しないでください。コードは明確に、理解可能なものにしてください。

function some_name( $some_variable ) {}

関数の引数名には、予約キーワードを使わないことを 強く推奨 します。これは PHP 8.0の「関数呼び出し内の名前付き引数」機能を使用する際に、読みづらく、混乱したコードになるためです。 また、関数の引数名を変更することは PHP 8.0以降は破壊的な変更と見なされることに注意してください。

クラス名、トレイト名、インターフェース名、列挙体名は、大文字で始まる単語をアンダースコアで区切ります。省略語はすべて大文字にします。

class Walker_Category extends Walker {}
class WP_HTTP {}

interface Mailer_Interface {}
trait Forbid_Dynamic_Properties {}
enum Post_Status {}

定数はすべて大文字で、アンダースコアで区切ります。

define( 'DOING_AJAX', true );

ファイル名はアルファベットの小文字を使用して、内容を説明する名前にしてください。単語はハイフンで区切ります。

my-plugin-name.php

クラスファイルの名前はクラス名を基にして、前に「class-」を付け、クラス名内部のアンダースコアはハイフンで置き換えます。 たとえば「WP_Error」の場合

class-wp-error.php

このファイルの命名規則は、テスト用のクラスを除いて、クラスを含むすべての現行および新規のファイルに適用されます。テストクラスを含むファイルについては PSR4 に従ってファイル名にクラス名を正確に反映しなければなりません。これにより、すべてのサポート PHPUnit バージョンにおけるバージョン間の互換性 が保証されます。

wp-includes ディレクトリ内のテンプレートタグを含むファイルには、分かりやすさのため名前の末尾に -template を付けてくだださい。

general-template.php

ダイナミックフック名での変数展開の利用

ダイナミックフックの名前では読みやすさ、検索のしやすさのため、変数の連結でなく、展開を使用してください。

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

フックタグで使用される変数は中括弧(「{」と「}」)で囲み、完全なタグ名全体をダブルクォートで囲んでください。こうすると PHP は、挿入された文字列内で指定された変数の型を正しくパースできます。

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

このときタグ名内の動的な値はできるだけ簡潔で分かりやすいものにしてください。$user_id の方がたとえば $this->id などよりも明確です。

スペース

スペースの使い方

コンマの後ろや、論理演算子、比較演算子、算術演算子、比較演算子、文字列演算子、代入演算子の両側には、常にスペース (空白文字) を入れてください。

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

制御構造ブロックの開き括弧、閉じ括弧の両側にも入れてください。

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

関数を定義する場合は、次の形式に従ってください。

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

function my_other_function() { ...

関数を呼び出す場合

my_function( $param1, func_param( $param2 ) );
my_other_function();

論理比較の場合

if ( ! $foo ) { ...

型のキャスト は小文字です。常に短い形式を使用してください。(integer) でなく (int)(boolean) でなく (bool)。float については (float) を使用してください。(real) は使いません。PHP 7.4 で 非推奨、PHP 8 で削除されています。

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

$foo = (bool) $bar;

配列要素を参照する場合には、添字が変数の場合のみ前後にスペースを入れてください。

$x = $foo['bar']; // 正しい
$x = $foo[ 'bar' ]; // 間違い

$x = $foo[0]; // 正しい
$x = $foo[ 0 ]; // 間違い

$x = $foo[ $bar ]; // 正しい
$x = $foo[$bar]; // 間違い

switch ブロックでは、case の条件とコロンの間にスペースを置かないでください。

switch ( $foo ) {
	case 'bar': // 正しい
	case 'ba' : // 間違い
}

特に指定のない限り、括弧はそれぞれの内側にスペースを置いてください。

if ( $foo && ( $bar || $baz ) ) { ...

my_function( ( $x - 1 ) * 5, $y );

加算子(++)または減算子(--)を使用するとき、演算子と適用する変数の間にスペースは挿入できません。

// 正しい
for ( $i = 0; $i < 10; $i++ ) {}

// 間違い
for ( $i = 0; $i < 10; $i ++ ) {}
++   $b; // 複数のスペース

インデント

インデントは常に論理的な構造を反映してください。インデントには本物のタブを使用します。スペースは使わないでください。大部分のクライアント環境で最大の柔軟性を得られます。

例外: コードブロックの可読性のために、必要であれば、スペースを使用してください。

[tab]$foo   = 'somevalue';
[tab]$foo2  = 'somevalue2';
[tab]$foo34 = 'somevalue3';
[tab]$foo5  = 'somevalue4';

連想配列で複数の要素を含む場合、各項目 を、新しい行で始めてください。

$query = new WP_Query( array( 'ID' => 123 ) );

$args = array(
[tab]'post_type'   => 'page',
[tab]'post_author' => 123,
[tab]'post_status' => 'publish',
);

$query = new WP_Query( $args );

注意: 配列の最後の要素に続くコンマは推奨です。配列の要素を簡単に並べ替えることができ、新しい項目が追加されても diff の結果が明確です。

$my_array = array(
[tab]'foo'   => 'somevalue',
[tab]'foo2'  => 'somevalue2',
[tab]'foo3'  => 'somevalue3',
[tab]'foo34' => 'somevalue3',
);

switch 制御構造では、case 文は switch 文から1タブ分インデントし、case の内容は case の条件文から1タブ分インデントしてください。

switch ( $type ) {
[tab]case 'foo':
[tab][tab]some_function();
[tab][tab]break;
[tab]case 'bar':
[tab][tab]some_function();
[tab][tab]break;
}

ルール: 行の先頭はタブでインデントし、途中を揃える場合にスペースを使用してください。

文末の空白の除去

各行末尾のスペースは削除してください。ファイル末尾の PHP 終了タグの除去は推奨です。終了タグを使用する場合には、その後にスペースがないことを確認してください。

関数本体の末尾の空白行は削除してください。

フォーマット

ブレース (波括弧、中括弧) の形式

すべてのブロックに対して以下の形式でブレースを使用してください。

if ( condition ) {
    action1();
    action2();
} elseif ( condition2 && condition3 ) {
    action3();
    action4();
} else {
    defaultaction();
}

その上で非常に長いブロックがあれば、複数の短いブロック、関数、メソッドに分割できないかを検討してください。分割することで複雑度を解消し、テストしやすくなり、可読性を向上できます。

ブレースは必ず使用してください。省略可能な場合でも使用してください。

if ( condition ) {
    action0();
}

if ( condition ) {
    action1();
} elseif ( condition2 ) {
    action2a();
    action2b();
}

foreach ( $items as $item ) {
    process_item( $item );
}

注意: ブレースの使用を義務付けるということは、「単一文のインライン制御構造」の禁止を意味します。「制御構造に関する別の構文」は使用しても構いません (例: 「if」と「endif」、「while」と「endwhile」)。これらは例えば、テンプレート内で HTML に PHPコードを埋め込む際に使用されます。

<?php if ( have_posts() ) : ?>
    <div class="hfeed">
        <?php while ( have_posts() ) : the_post(); ?>
            <article id="<?php echo esc_attr( 'post-' . get_the_ID() ); ?>" class="<?php echo esc_attr( get_post_class() ); ?>">
                <!-- ... -->
            </article>
        <?php endwhile; ?>
    </div>
<?php endif; ?>

配列の宣言

配列の宣言では、一般に長い配列構文 (array( 1, 2, 3 )) の方が短い配列構文 ([ 1, 2, 3 ]) よりも可読性に優れます。これは主に視覚的な面からから来ますが、加えて初心者にとっても分かりやすくなります。

配列は常に長い配列構文で宣言してください。

複数行での関数呼び出し

関数呼び出しを複数行に分割する場合、1行ずつパラメータを並べてください。インラインコメントも単体で1行にしてください。

各パラメータはそれ以上複数行に分割しないでください。複数行必要なパラメータ値は、まず変数に割り当て、次にその変数を関数呼び出しに指定してください。

$bar = array(
    'use_this' => true,
    'meta_key' => 'field_name',
);
$baz = sprintf(
    /* translators: %s: Friend's name */
    __( 'Hello, %s!', 'yourtextdomain' ),
    $friend_name
);

$a = foo(
    $bar,
    $baz,
    /* translators: %s: cat */
    sprintf( __( 'The best pet is a %s.' ), 'cat' )
);

型宣言

型宣言では型の前後に、正確に1つのスペースを挿入しなければなりません。nullabile な演算子 (?) は型宣言の一部とみなされ、この演算子と実際の型の間にスペースは挿入できません。クラス名、インターフェース名、列挙体名に基づく型宣言では、これらの名前の宣言と同じ大文字、小文字を使用する必要があります。一方、キーワードに基づく型宣言では、小文字を使用しなければなりません。

戻り値の型宣言では関数宣言の閉じ括弧と、戻り値の型を始めるコロンの間にスペースを挿入しないでください。

以上のルールは型宣言を許可するすべての構造に適用されます: 関数、クロージャ、列挙型、catch 条件、PHP 7.4のアロー関数、型付きプロパティ。

// 正しい
function foo( Class_Name $parameter, callable $callable, int $number_of_things = 0 ) {
    // 何かを実行する
}

function bar(
    Interface_Name&Concrete_Class $param_a,
    string|int $param_b,
    callable $param_c = 'default_callable'
): User|false {
    // 何かを実行する
}

// 間違い
function baz(Class_Name $param_a, String$param_b,      CALLABLE     $param_c )   :   ?   iterable   {
    // 何かを実行する
}

型宣言の使用には、WordPress コア、プラグイン、テーマのいずれであっても、アプリケーションに最低限必要な PHP バージョンに基づく以下の制限があります:

  • スカラー型 boolintfloatstring の型宣言は、サポートする最低バージョンが PHP 7.0 以降になるまでは使用できません。
  • 戻り値の型宣言は、サポートする最低バージョンが PHP 7.0 以降になるまでは使用できません。
  • Nullable 型の宣言は、サポートする最低バージョンが PHP 7.1 以降になるまでは使用できません。
  • iterable および void 型の宣言は、サポートする最低バージョンが PHP 7.1 以降になるまでは使用できません。void 型は戻り値としてのみ使用できます。
  • object 型の宣言は、サポートする最低バージョンが PHP 7.2 以降になるまでは使用できません。
  • プロパティの型宣言は、サポートする最低バージョンが PHP 7.4 以降になるまでは使用できません。
  • static 型 (戻り値の型のみ) は、サポートする最低バージョンが PHP 8.0 以降になるまでは使用できません。
  • mixed 型は、サポートする最低バージョンが PHP 8.0 以降になるまでは使用できません。注意: mixed 型には null が含まれるため、nullable にはできません。
  • union 型は、サポートする最低バージョンが PHP 8.0 以降になるまでは使用できません。
  • 交差型は、サポートする最低バージョンが PHP 8.1 以降になるまでは使用できません。
  • never 型 (戻り値の型のみ) は、サポートする最低バージョンが PHP 8.1 以降になるまでは使用できません。
  • 選言標準形 (論理和型と論理積型の組み合わせ) は、サポートする最低バージョンが PHP 8.2 以降になるまでは使用できません。

WordPress コアでの使用

警告: 既存のWordPress コアの関数への型宣言の追加は、細心の注意を払ってください。

プラグインやテーマで上書きされる可能性のある関数 (メソッド) のシグネチャは、触るべきではありません。 現時点で型宣言を追加する余地があるものは、グローバル名前空間で無条件に宣言された関数、private クラスのメソッド、コアに新しく追加されたコードだけです。

注意:型宣言で array キーワードを使用することは、現時点で 強く推奨されません 。ほとんどの場合、iterable を使用した方が実装の柔軟性が高くなりますし、このキーワードは最低要件が PHP 7.1 に上がるまで WordPress コアでは使用できません。

マジック定数

PHP ネイティブの __*__ マジック定数、例えば __CLASS__ や __DIR__ は大文字でなければなりません。

クラス名の解決に ::class 定数を使用する場合、class キーワードは小文字にし、:: 演算子の前後にはスペースを入れないでください。

// 正しい
add_action( 'action_name', array( __CLASS__, 'method_name' ) );
add_action( 'action_name', array( My_Class::class, 'method_name' ) );

// 間違い
require_once __dIr__ . '/relative-path/file-name.php';
add_action( 'action_name', array( My_Class :: CLASS, 'method_name' ) );

スプレッド演算子 …

スプレッド演算子を使用する場合、スプレッド演算子の前にスペースを1つ空けるか、適切なインデントで改行しなければなりません。スプレッド演算子とそれが適用される変数、関数呼び出しの間にはスペースを挿入しないでください。スプレッド演算子と参照演算子 (&) を組み合わせる場合も、その間にスペースを挿入しないでください。

// 正しい
function foo( &...$spread ) {
    bar( ...$spread );

    bar(
        array( ...$foo ),
        ...array_values( $keyed_array )
    );
}

// 間違い
function fool( &   ... $spread ) {
    bar(...
             $spread );

    bar(
        [...  $foo ],... array_values( $keyed_array )
    );
}

メモ: スプレッド演算子 (他の言語では splat 演算子として知られる) は、PHP 5.6以降で、関数宣言 (可変長引数関数) での引数のパックや関数呼び出しでの引数のアンパックに使用できます。PHP 7.4以降では、スプレッド演算子は数値添字付き配列のアンパックに、PHP 8.1以降では文字列キー付き配列のアンパックにも使用できます。 関数宣言で使用する場合、スプレッド演算子は、最後のパラメータでのみ使用できます。

文、名前空間、インポート文の宣言

名前空間の宣言

名前空間の名前は、先頭が大文字の単語と、アンダースコアの区切りから構成してください。

名前空間の宣言は、宣言の前に正確に1行の空白行を入れ、宣言の後に少なくとも1行の空白行を入れてください。

namespace Prefix\Admin\Domain_URL\Sub_Domain\Event; // 正しい

名前空間の宣言は1ファイルにつき1つだけとし、ファイルの先頭に記述してください。中括弧を使用した名前空間宣言は使用できません。明示的なグローバル名前空間宣言 (名前のない名前空間宣言) も使用できません。

// 間違い: 中括弧構文を使用した名前空間宣言
namespace Foo {
    // コード
}

// 間違い: グローバル名前空間での名前空間宣言
namespace {
    // コード
}

WordPress コアへの名前空間の導入時期は、現在、未定です。

プラグインやテーマでの名前空間の使用を強く推奨します。他のプラグインやテーマ、WordPress コアとの名前の衝突を防ぐために、できるだけ多くのコードに接頭辞を付けてください。

ただし、競合を防ぐために、十分な長さのユニークな名前空間接頭辞を使用してください。一般には、Vendor\Project_Nameのような、会社名とプロジェクト名の組み合わせの名前空間接頭辞を使用すると良いでしょう。

警告: 名前空間接頭辞 wp と WordPress は WordPress 用に予約されています。

名前空間は、変数、define()で宣言された定数、WordPress で使用されるフック名などの非 PHP ネイティブな構成要素には影響しません。 これらには、従来どおり個別に接頭辞をつける必要があります。

インポートの use 文の使用

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

インポートの use 文はファイルの先頭に記述し、オプションで namespace 宣言の後に記述します。これらはインポートの タイプ に基づいた特定の順序に従う必要があります。

  1. use 文 – 名前空間、クラス、インターフェース、トレイト、列挙型
  2. use 文 – 関数
  3. use 文 – 定数

エイリアスは使用できます。異なる名前空間の2つのクラスが同じクラス名を使用することで生じる、名前の衝突を防止できます。 エイリアスを使用する場合は WordPress の命名規則に従い、一意であることを確認してください。

以下の例では、スペース、グループ化、先頭のバックスラッシュなど、インポートの use 文の正しい使い方と間違った使い方を紹介しています。

正しい:

namespace Project_Name\Feature;

use Project_Name\Sub_Feature\Class_A;
use Project_Name\Sub_Feature\Class_C as Aliased_Class_C;
use Project_Name\Sub_Feature\{
    Class_D,
    Class_E as Aliased_Class_E,
}

use function Project_Name\Sub_Feature\function_a;
use function Project_Name\Sub_Feature\function_b as aliased_function;

use const Project_Name\Sub_Feature\CONSTANT_A;
use const Project_Name\Sub_Feature\CONSTANT_D as ALIASED_CONSTANT;

// 残りのコード

間違い:

namespace Project_Name\Feature;

use   const   Project_Name\Sub_Feature\CONSTANT_A; // use と const キーワードの後に余計なスペース
use function Project_Name\Sub_Feature\function_a; // 定数インポートの後に関数インポート
use \Project_Name\Sub_Feature\Class_C as aliased_class_c; // 先頭にバックスラッシュは使えない。エイリアスが命名規則に従っていない。
use Project_Name\Sub_Feature\{Class_D, Class_E   as   Aliased_Class_E} // as キーワードの前後に余計なスペース。中括弧内部の誤ったスペース
use Vendor\Package\{ function function_a, function function_b,
     Class_C,
        const CONSTANT_NAME}; // 1つの use 文中に異なるタイプのインポートが組み合わさっている。グループ use 文の中に誤ったスペース

class Foo {
    // コード
}

use const \Project_Name\Sub_Feature\CONSTANT_D as Aliased_constant; // クラス定義の後のインポート、先頭のバックスラッシュ、命名規則違反
use function Project_Name\Sub_Feature\function_b as Aliased_Function; // クラス定義の後のインポート、命名規則違反

// 残りのコード

警告: インポートの use 文は動的なクラス、関数、定数名には影響しません。use 文のグループは PHP 7.0から使用可能です。グループの use 文の末尾にカンマをつけることは PHP 7.2から可能です。

ヒント: 自動ロードを実装していない限り、use 文はインポートされるものを自動的にロードしないことに注意してください。インポートする構成要素を使用の際にロードするには、自動ロードをセットアップするか、require/import 文を使用してクラス、関数、定数を含むファイルをロードする必要があります。

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

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

インポートの use 文は、名前空間やクラスの自動ロード実装と組み合わせたときに最も有用です。 現在、WordPress コアではこのどちらも実装されておらず、この件に関する議論が進行中です。このため WordPress コアではインポートの use 文の追加を控えることが、今のところ賢明な選択です。

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

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

例えば、ファイル class-example-class.php には1つのクラスしか入れられません。

// 間違い: ファイル class-example-class.php
class Example_Class { [...] }

class Example_Class_Extended { [...] }

2つ目のクラスは、個別のファイル class-example-class-extended.php に置きます。

// 正しい: ファイル class-example-class.php
class Example_Class { [...] }

// 正しい: ファイル class-example-class-extended.php
class Example_Class_Extended { [...] }

トレイトの use 文

トレイトの use 文はクラスの先頭に記述し、最初の use 文の前には正確に1行の空白行を、最後の use 文の後には少なくとも1行の空白行を記述します。唯一の例外は、クラスがトレイトの use 文のみを含む場合で、その場合は後ろの空白行を省略できます。

以下のコード例では、スペース、グループ化、インデントなどに関して、トレイトの use 文に必要な書式を示します。

// 正しい
class Foo {

    use Bar_Trait;
    use Foo_Trait,
        Bazinga_Trait {
        Bar_Trait::method_name insteadof Bar_Trait;
        Bazinga_Trait::method_name as bazinga_method;
    }
    use Loopy_Trait {
        eat as protected;
    }

    public $baz = true;

    ...
}

// 間違い
class Foo {
    // トレイトの use 文の前に空白行がない、use キーワードの後に複数のスペース。
    use       Bar_Trait;

    /*
     * トレイトのインポート時に複数のスペース、開き中括弧の後に開業なし。
     * エイリアスは置換するメソッドと同じ行でなければならない。
     */
    use Foo_Trait,   Bazinga_Trait{Bar_Trait::method_name    insteadof     Foo_Trait; Bazinga_Trait::method_name
        as     bazinga_method;
            }; // 不正なインデントの中括弧
    public $baz = true; // トレイトのインポートの後に空白行がない

    ...
}

アクセス権 (Visibility) を常に宣言する

アクセス権を宣言可能なすべての構成要素 (プロパティ、メソッド、PHP 7.1 以降のクラス定数) について、明示的にアクセス権を宣言しなければなりません。 プロパティの宣言に var キーワードは使用できません。

// 正しい
class Foo {
    public $foo;

    protected function bar() {}
}

// 間違い
class Foo {
    var $foo;

    function bar() {}
}

WordPress コアでの使用

WordPress コアでは、サポートするPHP の最小バージョンが PHP 7.1に上がるまでは、クラス定数のアクセス権を使用できません。

アクセス権 (Visibility) と修飾子の順番

複数の修飾子を クラス宣言 に使用する場合、次の順序に従ってください。

  1. まず、オプションの abstract または final 修飾子
  2. 次に、オプションの readonly 修飾子

複数の修飾子をオブジェクト指向構造体の内部の 定数宣言 に使用する場合、次の順序に従ってください。

  1. まず、オプションの final 修飾子
  2. 次に、アクセス権修飾子

複数の修飾子を プロパティ宣言 に使用する場合、次の順序に従ってください。

  1. まず、アクセス権修飾子
  2. 次に、オプションの static または readonly 修飾子 (これらのキーワードは互いに排他的)
  3. 最後に、オプションの type 宣言

複数の修飾子を メソッド宣言 に使用する場合、次の順序に従ってください。

  1. まず、オプションの abstract または final 修飾子
  2. 次に、アクセス権修飾子
  3. 最後に、オプションの static 修飾子
// 正しい
abstract readonly class Foo {
    private const LABEL = 'Book';

    public static $foo;

    private readonly string $bar;

    abstract protected static function bar();
}

// 間違い
class Foo {
    protected final const SLUG = 'book';

    static public $foo;

    static protected final function bar() {
        // コード
    };
}

ヒント:

  • OO 定数のアクセス権は、PHP 7.1 以降で宣言できます。
  • 型付きプロパティは、PHP 7.4 以降で使用できます。
  • リードオンリープロパティは、PHP 8.1 以降で使用できます。
  • オブジェクト指向構造体内の定数の final 修飾子は、PHP 8.1 以降で使用できます。
  • リードオンリークラスは、PHP 8.2 以降で使用できます。

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

新しいオブジェクトインスタンスをインスタンス化するときは、厳密に必要でない場合でも、常に括弧を使用しなければなりません。 インスタンス化されるクラス名と始まりの括弧の間にはスペースを入れないでください。

// 正しい
$foo = new Foo();
$anonymous_class = new class( $parameter ) { ... };
$instance = new static();

// 間違い
$foo = new Foo;
$anonymous_class = new class ( $input ) { ... };

制御構造

「elseif」を使う。「else if」は使わない

「else if」は「if|elseif」ブロックのコロン構文と互換性がありません。条件式では「elseif」を使用してください。

ヨーダ記法

if ( true === $the_force ) {
    $victorious = you_will( $be );
}

変数を伴う論理比較を行う場合、常に変数を右側に、定数や文字列や関数呼び出しを左側に置いてください。どちらも変数でなければ、順序は重要ではありません (コンピューターサイエンスの言葉では、比較時、常に l-value を右意、r-value を左に置きます)。

上の例で1つ等号を忘れると、パースエラーが発生します (白状すると、熟練のコアメンバーでもやらかします)。定数 true に代入できないためです。もし条件式が ( $the_force = true ) であれば、代入は構文として正しく 1 を返し、結果 if 文は true と評価し、そして、しばらくバグと闘うことになるでしょう。

ヨーダ記法は最初、奇妙に見えるかもしれませんが、そのうち慣れるはずです。

なおヨーダ記法は「==」「!=」「===」「!==」で使用してください。「<」「>」「<=」「>=」では読みづらいため避けてください。

演算子

三項演算子

三項演算子は使用しても構いませんが、常に文が true かどうかをテストしてください。false のテストは混ぜないでください、混乱するだけです。ただし「! empty()」の場合は例外です。この場合は false のテストのほうが直感的でしょう。

短い形式の三項演算子は使用しないでください。

例:

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

エラー制御演算子 @

PHP ドキュメント にあるように、

PHP はエラー制御演算子(@)をサポートしています。PHP の式の前に付けた場合、その式で起こる可能性のある診断エラーは抑制されます。

この演算子がコア内に存在すると、適切なエラーチェックが行われずしばしば遅れて適用されます。決して使用しないでください。ちなみに PHP のドキュメントにさえ次のような箇所があります。

PHP 8.0.0 より前のバージョンでは、 スクリプトの実行を停止させるような致命的な場合であっても @ 演算子でエラーメッセージを抑止することが可能でした。 たとえば、存在しなかったり、ミスタイプされていたり、 利用できない関数コールの前に @ 演算子を付けると、 原因を示すことなく、その場所でスクリプトは終了してしまっていました。

加算子 / 減算子

スタンドアロンの文では、前置加算子、前置減算子が、後置加算子、後置減算子に優先します。

前置加算子、前置減算子は、インクリメント、デクリメントしてから値を戻します。一方、後置加算子、後置減算子は値を戻してから、インクリメント、デクリメントします。 「前置」バージョンの方が若干パフォーマンスに優れ、また将来コードが移動したときのバグを防ぐことができます。

// 正しい。前置減算子
--$a;

// 間違い。後置減算子
$a--;

データベース

データベースクエリ

データベースには直接触らないでください。必要なデータを取得する関数があれば、それを使用してください。クエリの代わりに関数を使用したデータベースの抽象化を利用すると、コードは前方互換性を保ち、結果がメモリー内にキャッシュされる場合は何倍も速くなります。

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

SQL 文の書式

SQL 文が非常に複雑な場合は、複数行に分割し、インデントしても構いません。大部分の SQL 文は1行の場合と同様に動作するはずです。文の SQL の部分は「UPDATE」や「WHERE」のように常に大文字にしてください。

データベースを更新する関数は、渡されたパラメータが SQL 用にエスケープされていないと仮定して処理してください。エスケープはできるだけクエリの直前に、可能であれば「$wpdb->prepare()」を使用して実行してください。

$wpdb->prepare()」は SQL クエリのエスケープ、クォート、整数へのキャストを処理するメソッドです。sprintf() 書式のサブセットを使用します。 例:

$var = "dangerous'"; // 生データ。エスケープしてもしなくても良い
$id = some_foo_number(); // integer を期待するデータ。ただし確証はない

$wpdb-&gt;query( $wpdb-&gt;prepare( "UPDATE $wpdb-&gt;posts SET post_title = %s WHERE ID = %d", $var, $id ) );

クエリー文字列には次のプレースホルダーを使用できます:

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

注意: これらのプレースホルダを「クォートで囲まない」でください。wpdb->prepare() がエスケープとクォートを実行します。これはクエリーが発生したときに実行されるため、エスケープされたかどうかが一目で分かります。

詳細については、Plugin Handbook の「Data Validation」を参照してください。

推奨

関数の引数には意味のあるフラグ値を使用する

関数を呼び出す場合は、単に true や false を使用するのではなく、文字列値を使用してください。

// 間違い
function eat( $what, $slowly = true ) {
...
}
eat( 'mushrooms' );
eat( 'mushrooms', true ); // true って、どういうこと?
eat( 'dogfood', false ); // false って、どういうこと? true の反対ってこと?

PHP は 8.0 以降で名前付き引数をサポートします。しかし、WordPress は現在まだ古いバージョンの PHP をサポートしているため、まだ名前付き引数をを使用できません。 名前付き引数がない場合、フラグの値には意味がありません。この結果、上のような例に出会うたびに関数定義を探す必要が出てきます。ブール値の代わりに説明的な文字列値を使用することで、コードは読みやすくなります。

// 正しい
function eat( $what, $speed = 'slowly' ) {
...
}
eat( 'mushrooms' );
eat( 'mushrooms', 'slowly' );
eat( 'dogfood', 'quickly' );

関数パラメータに説明を加えたければ、配列 $args が良いパターンです。

function eat( $what, $args ) {
...
}
eat ( 'noodles', array( 'speed' =&gt; 'moderate' ) );

このパターンを使用する際には注意が必要です。使用前に入力を検証しなければ、警告「Undefined array index (未定義の配列インデックス)」になる場合があります。このパターンは、意味のある場合のみ使用してください (たとえば、複数の引数を指定する場合など)。

賢いコード

一般にコードの読みやすさは賢さや短さよりも重要です。

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

上のコードは賢いかもしれませんが、構文に慣れていなければ完全に理解するまで時間がかかります。それよりも次のように書くべきです。

if ( ! isset( $var ) ) {
    $var = some_function();
}

本当に必要でない限り、緩やかな比較 (loose comparison) は、動作を誤解しやすいため、使用しないでください。

正しい:

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

間違い:

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

条件の中で代入しないでください。

正しい:

$data = $wpdb-&gt;get_var( '...' );
if ( $data ) {
    // Use $data.
}

間違い:

if ( $data = $wpdb-&gt;get_var( '...' ) ) {
    // Use $data.
}

switch 文では、共通コードに落ちる複数の空白 case があっても構いません。しかし、case にコードがあって次のコードに落ちる場合にはその旨をコメントを記述してください。

switch ( $foo ) {
	case 'bar':	      // 正しい。空白の case はコメントなしで次に落ちて良い。
	case 'baz':
		echo $foo;    // 間違い。コードを含む case は break または returnで終えるか、コメントを含む必要がある。
	case 'cat':
		echo 'mouse';
		break;        // 正しい。break のある case にコメントは不要。
	case 'dog':
		echo 'horse';
		// no break   // 正しい。次に落ちる旨を明確に記述したコメントがある。
	case 'fish':
		echo 'bird';
		break;
}

goto 文は決して使わないでください。

eval() 構成要素は 非常に危険 で、安全性を保つことが不可能です。また create_function() 関数は内部的に eval() を実行し、PHP 8.0 では両方とも削除されました。両方の関数を使わないでください。

クロージャー (無名関数)

必要であれば、コールバックに渡す際、新規に関数を作成する代わりにクロージャーを使うことができます。例えば、

$caption = preg_replace_callback(
    '/&lt;[a-zA-Z0-9]+(?: [^&lt;&gt;]+&gt;)*/',
    function ( $matches ) {
        return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] );
    },
    $caption
);

クロージャーをフィルターやアクションのコールバックとして渡さないでください。remove_action() / remove_filter() による削除は、現時点では、複雑です (この問題を解決する提案については #46635 を参照してください)。

正規表現

POSIX 互換関数 ではなく、Perl 互換の正規表現 (PCRE preg_ 関数) を使用してください。決して「/e」修飾子は使わず、代わりに「preg_replace_callback」を使用してください。

正規表現には、一重引用符で囲む文字列を使用するほうが便利です。二重引用符で囲む文字列とは異なり、一重引用符で囲む文字列には、エスケープが必要なものは、2つのメタシークエンス「\’」と「\\」しかないためです。

extract() は使わない

#22400: Remove all, or at least most, uses of extract() within WordPress によれば、

extract() はひどい関数。コードはデバッグしにくいし、読みにいし。使うのは禁止して、中で使ってるのも全部削除しよう。

Joseph Scott が 何がそんなにひどいのかを書いています

シェルコマンド

バッククォート演算子 (「`」)の使用は認められません。

バッククォート演算子の使用は、shell_exec() と同じです。セキュリティ上の理由からほとんどのホスティング環境では php.ini ファイルでこの関数が無効にされています。

原文 / 日本語訳

s
検索
c
新規投稿を作成する
r
返信
e
編集
t
ページのトップへ
j
次の投稿やコメントに移動
k
前の投稿やコメントに移動
o
コメントの表示を切替
esc
投稿やコメントの編集をキャンセル