2026年7月18日

2026年7月18日

WordPressプラグイン開発でPHPのnamespaceを使うベストプラクティス

WordPressプラグインでPHPのnamespace(名前空間)を使うと、関数名やクラス名に毎回長い接頭辞を付けなくても、他のプラグインとの名前の衝突を避けられます。ただし、フックへのコールバック指定やWordPressコアのクラスの呼び出しには、namespace特有の書き方が必要です。この記事では、名前の付け方、フック登録の正しい書き方、namespaceでは守れないものまでを、つまずきやすい点と合わせて説明します。

なお、ファイル構成とオートロードの組み立ては「PSR-4オートロード」の記事、外部ライブラリの管理は「Composer」の記事で扱っており、ここではnamespaceそのものの使い方に絞ります。

なぜnamespaceを使うのか

WordPressでは、すべてのプラグインとテーマのコードが同じPHPプロセスに読み込まれます。2つのプラグインが同じ get_settings() という関数を定義すると、後から読み込まれた側で致命的エラーになり、サイトが表示されなくなります。

従来は myplugin_get_settings() のように接頭辞を付けて避けてきました。namespaceを使うと、ファイルの先頭で一度宣言するだけで、そのファイル内の関数・クラス・定数がすべて Vendor\Plugin\get_settings のようなnamespace付きの名前を持つようになります。プラグインハンドブックのベストプラクティスでも、接頭辞かnamespaceで名前の衝突を防ぐよう勧めています。

PHPのnamespaceはPHP 5.3からある機能で、現在WordPressが動作要件とするPHPバージョンでは問題なく使えます(2026年10月現在)。プラグインのヘッダーには Requires PHP: で、実際に使っている構文に合わせた最低バージョンを書いておきます。

名前の付け方

namespaceは「ベンダー名\プラグイン名」の2段にするのが一般的です。

<?php
namespace Acme\BookShelf;
  • ベンダー名には会社名や個人名など、他と重なりにくいものを使う
  • WordPress や WP のような一般的な名前を先頭に使わない
  • 一度公開したら変えない(外部のコードが参照している可能性があるため)

機能が増えたら Acme\BookShelf\Admin、Acme\BookShelf\Rest のようにサブnamespaceで整理します。

基本の書き方とファイル先頭のルール

namespace 宣言は、ファイルの最初の文として書く必要があります。前に置けるのは <?php と declare(strict_types=1); だけで、HTMLや空白の出力、他のコードを先に書くとエラーになります。

<?php
/**
 * Plugin Name: Book Shelf
 * Requires PHP: 7.4
 */

namespace Acme\BookShelf;

defined( 'ABSPATH' ) || exit;

const VERSION = '1.0.0';

function plugin_dir(): string {
    return plugin_dir_path( __FILE__ );
}

const で定義した定数はnamespaceに属し、外からは \Acme\BookShelf\VERSION で参照します。define( 'VERSION', ... ) と書くと、namespaceの中でもグローバルな定数になる点に注意してください。

フックに渡すコールバックの書き方

namespaceを導入したときに最も多いのが、フックが動かない、または「関数が見つからない」というエラーです。add_action() に文字列で関数名を渡す場合、WordPressはその文字列をグローバルな名前として解釈するため、namespaceを含めた名前を渡す必要があります。

<?php
namespace Acme\BookShelf;

// 誤り:グローバル関数 register_post_types を探してしまう
add_action( 'init', 'register_post_types' );

// 正しい:namespace付きの名前を渡す
add_action( 'init', __NAMESPACE__ . '\\register_post_types' );

function register_post_types(): void {
    register_post_type( 'acme_book', array(
        'label'  => __( '書籍', 'book-shelf' ),
        'public' => true,
    ) );
}

__NAMESPACE__ は現在のnamespace名を返す定数です。手で 'Acme\\BookShelf\\register_post_types' と書いても動きますが、namespaceを変えたときに直し漏れが起きやすくなります。

クラスを使う場合は、配列でオブジェクトとメソッドを渡します。

<?php
namespace Acme\BookShelf;

class Plugin {
    public function register(): void {
        add_action( 'init', array( $this, 'register_post_types' ) );
        add_filter( 'the_content', array( $this, 'append_note' ) );
    }

    public function register_post_types(): void { /* ... */ }

    public function append_note( string $content ): string {
        return $content;
    }
}

フックの登録はコンストラクタの中ではなく、register() のような専用メソッドで行うと、テストのときにオブジェクトを作るだけでフックが登録される事態を避けられます。

無名関数でも登録できますが、後から remove_action() で外せなくなります。他の開発者が挙動を変えたい可能性があるフックには、名前のある関数かメソッドを使ってください。

コアのクラスを使うときの「\」

namespaceの中では、関数と定数は見つからなければグローバルに自動でフォールバックしますが、クラスはフォールバックしません。そのため、namespace内で new WP_Query() と書くと、PHPは Acme\BookShelf\WP_Query を探し、「Class not found」の致命的エラーになります。

<?php
namespace Acme\BookShelf;

use WP_Query;
use WP_Error;

function latest_books(): array {
    $query = new WP_Query( array(
        'post_type'      => 'acme_book',
        'posts_per_page' => 5,
        'no_found_rows'  => true,
    ) );
    return $query->posts;
}

function validate( $value ) {
    if ( '' === $value ) {
        return new WP_Error( 'empty', __( '値が空です', 'book-shelf' ) );
    }
    try {
        // ...
    } catch ( \Exception $e ) {
        // 例外クラスも先頭に \ が必要
    }
    return $value;
}

ファイルの先頭で use を書くか、使う場所で \WP_Query のように先頭に \ を付けるかのどちらかで解決します。Exception や DateTime のようなPHP標準のクラスも同じです。

function_exists() や class_exists() に渡す名前も、namespaceを含めた名前で書きます。

namespaceでは守れないもの

namespaceが守るのはPHPの関数・クラス・定数の名前だけです。次のものはWordPress側の共有の名前空間にあるため、従来どおり接頭辞が必要です。

  • オプション名、トランジェント名、ユーザーメタや投稿メタのキー
  • 独自に作るフック名(do_action( 'acme_bookshelf_saved' ) など)
  • カスタム投稿タイプやタクソノミーのスラッグ、ショートコード名
  • wp_enqueue_script() などのハンドル名、REST APIのnamespace
  • 独自に作るデータベーステーブル名
  • JavaScriptのグローバル変数や、CSSのクラス名

特にカスタム投稿タイプのスラッグは20文字以内という制限があるため、短い接頭辞を決めておくと扱いやすくなります。

同じライブラリを同梱するプラグイン同士の衝突

自分のコードにnamespaceを付けても、Composerなどで同梱した外部ライブラリのクラス名はそのままです。別のプラグインが同じライブラリの別バージョンを同梱していると、先に読み込まれた側のクラスが使われ、意図しない不具合が起きます。配布するプラグインでは、同梱するライブラリのnamespaceに接頭辞を付け直すツール(Strauss や PHP-Scoper など)を使う方法があります。詳しくはComposerの記事で扱います。

動作確認のポイント

  • wp-config.php で WP_DEBUG と WP_DEBUG_LOG を有効にし、wp-content/debug.log に「Call to undefined function」や「Class not found」が出ていないかを見る
  • エラーにnamespace付きの名前(例: Acme\BookShelf\WP_Query)が出ていたら、use か \ の付け忘れを疑う
  • フックが動いているかは、Query Monitorなどのデバッグ用プラグインで登録状況を確認できる

本番サイトで試すと、致命的エラーで管理画面に入れなくなることがあります。開発はローカルかステージング環境で行い、万一のときはFTPなどでプラグインのフォルダ名を変えて停止できることを確認しておいてください。

まとめ

  • namespaceは Vendor\Plugin の2段で、ファイルの最初の文として宣言する
  • 文字列のコールバックは __NAMESPACE__ . '\\関数名' のようにnamespace付きの名前で渡す
  • クラスはグローバルにフォールバックしないため、use WP_Query; か \WP_Query と書く
  • オプション名・フック名・投稿タイプなどは、namespaceとは別に接頭辞が必要
  • 同梱ライブラリの衝突は、namespaceの付け直しツールで防ぐ

お気軽にご相談ください

お見積りへ お問い合わせへ
▲