WordPressプラグインとテーマのオートローディングとネームスペース:動作しますか?


70

プラグインまたはテーマ内でオートローディングやPHP名前空間を使用している人はいますか?

それらを使用することについての考え?害はありますか?落とし穴?

注:名前空間はPHP 5.3以降のみです。この質問では、PHP 5.3以降を使用していることがわかっているサーバーを扱うことを知っていると仮定します。

回答:


88

さて、名前空間とオートロードに依存するのに十分なほどサーバーを制御している2つの大きなプロジェクトがありました。

最初に。オートロードは素晴らしいです。requireを心配しないことは比較的良いことです。

これが私がいくつかのプロジェクトで使っているローダーです。最初にクラスが現在のネームスペースにあることを確認し、そうでない場合はベイルします。そこから、クラスを見つけるための単なる文字列操作です。

<?php
spl_autoload_register(__NAMESPACE__ . '\\autoload');
function autoload($cls)
{
    $cls = ltrim($cls, '\\');
    if(strpos($cls, __NAMESPACE__) !== 0)
        return;

    $cls = str_replace(__NAMESPACE__, '', $cls);

    $path = PLUGIN_PATH_PATH . 'inc' . 
        str_replace('\\', DIRECTORY_SEPARATOR, $cls) . '.php';

    require_once($path);
}

名前空間なしで使用するためにこれを簡単に適合させることができます。プラグイン/テーマのクラスに均一にプレフィックスを付けると仮定すると、そのプレフィックスをテストできます。次に、クラス名にアンダースコアを使用して、ディレクトリ区切りのプレースホルダーとして使用します。多数のクラスを使用している場合は、何らかのクラスマップオートローダーを使用することをお勧めします。

名前空間とフック

WordPressのフックシステムは、call_user_func(およびcall_user_func_array)を使用して機能します。これは、関数名を文字列として受け取りdo_actioncall_user_func関数呼び出しが行われたときに呼び出します。

名前空間を使用すると、名前空間を含む完全修飾関数名をフックに渡す必要があります。

<?php
namespace WPSE\SomeNameSpace;

add_filter('some_filter', 'WPSE\\SomeNameSpace\\the_function');
function the_function()
{
   return 'did stuff';
}

これを行うには、おそらく__NAMESPACE__マジック定数をリベラルに使用することをお勧めします。

<?php
namespace WPSE\SomeNameSpace;

add_filter('some_filter', __NAMESPACE__ . '\\the_function');
function the_function()
{
   return 'did stuff';
}

フックを常にクラスに入れると、簡単になります。標準のクラスのインスタンスおよびコンストラクター内のすべてのフックは、$this正常に機能します。

<?php
namespace WPSE\SomeNameSpace;

new Plugin;

class Plugin
{
    function __construct()
    {
        add_action('plugins_loaded', array($this, 'loaded'));
    }

    function loaded()
    {
        // this works!
    }
}

私がやりたいような静的メソッドを使用する場合、完全修飾クラス名を配列の最初の引数として渡す必要があります。これは大変な作業なので、魔法の__CLASS__定数orを使用するだけget_classです。

<?php
namespace WPSE\SomeNameSpace;

Plugin::init();

class Plugin
{
    public static function init()
    {
        add_action('plugins_loaded', array(__CLASS__, 'loaded'));
        // OR: add_action('plugins_loaded', array(get_class(), 'loaded'));
    }

    public static function loaded()
    {
        // this works!
    }
}

コアクラスの使用

PHPのクラス名解決は少し不安定です。コアWPクラスを使用する場合(WP_Widget以下の例)、useステートメントを提供する必要があります。

use \WP_Widget;

class MyWidget extends WP_Widget
{
   // ...
}

または、完全修飾クラス名を使用することもできます。基本的には、バックスラッシュを前に付けるだけです。

<?php
namespace WPSE\SomeNameSpace;

class MyWidget extends \WP_Widget
{
   // ...
}

定義する

これはより一般的なPHPですが、私には噛み付きますので、ここにあります。

プラグインへのパスなど、頻繁に使用するものを定義することもできます。defineステートメントを使用すると、名前空間をdefineの最初の引数に明示的に渡さない限り、ルート名前空間に物が置かれます。

<?php
namespace WPSE\SomeNameSpace;

// root namespace
define('WPSE_63668_PATH', plugin_dir_path(__FILE__));

// in the current namespace
define(__NAMESPACE__ . '\\PATH', plugin_dir_path(__FILE__));

constPHP 5.3プラスのファイルのルートレベルでキーワードonを使用することもできます。 constssは常に現在のネームスペースにありますが、define呼び出しほど柔軟ではありません。

<?php
namespace WPSE\SomeNameSpace;

// in the current namespace
const MY_CONST = 1;

// this won't work!
const MY_PATH = plugin_dir_path(__FILE__);

あなたが持っているかもしれない他のヒントを自由に追加してください!


16

これが2017年の答えです。

オートロードは素晴らしいです。名前空間は素晴らしいです。

自分でロールバックすることもできますが、2017年には、素晴らしく遍在するComposerを使用してPHPの要件を処理することが最も理にかなっています。ComposerはPSR-0PSR-4の両方の自動ロードをサポートしていますが、前者は2014年以降廃止されているため、PSR-4を使用してください。ディレクトリの複雑さを軽減します。

プラグイン/テーマはそれぞれ独自のGithubリポジトリに保持され、それぞれに独自のcomposer.jsonファイルとcomposer.lockファイルがあります。

プラグインに使用するディレクトリ構造は次のとおりです。(というプラグインは実際にはありませんが、awesome-plugin必要です。)

plugins/awesome-plugin/bootstrap.php
plugins/awesome-plugin/composer.json
plugins/awesome-plugin/composer.lock
plugins/awesome-plugin/awesome-plugin.php
plugins/awesome-plugin/src/*

plugins/awesome-plugin/vendor/autoload.php
plugins/awesome-plugin/vendor/*

適切なcomposer.jsonファイルを提供すると、Composerはここで名前の間隔と自動読み込みを処理します。

{
    "name": "awesome-company/awesome-plugin",
    "description": "Wordpress plugin for AwesomeCompany website, providing awesome functionality.",
    "type": "wordpress-plugin",
    "autoload": {
        "psr-4": {
            "AwesomeCompany\\Plugins\\AwesomePlugin\\": "src"
        }
    }
}

を実行composer installすると、vendorディレクトリとvendor/autoload.phpファイルが作成されます。これらのファイルは、にあるすべての名前空間ファイルとsrc/、必要な他のライブラリを自動ロードします。

次に、メインプラグインファイル(これはawesome-plugin.php)の上部で、プラグインメタデータの後に、次のものが必要です。

// Composer autoloading.
require_once __DIR__ . '/vendor/autoload.php';

...

ボーナス機能

必ずしも必要ではありませんが、最初からComposer を使用するには、Bedrock Wordpressボイラープレートを使用します。その後、Composerを使用して、Composerを介して必要なプラグインをアセンブルできます。これには、上記で作成した独自のプラグインも含まれます。また、おかげWPackagistは、あなたがWordpress.orgから、他のプラグインを必要とすることができます(例を参照cool-themeしてcool-plugin以下に)。

{
  "name": "awesome-company/awesome-website",
  "type": "project",
  "license": "proprietary",
  "description": "WordPress boilerplate with modern development tools, easier configuration, and an improved folder structure",
  "config": {
    "preferred-install": "dist"
  },
  "repositories": [
    {
      "type": "composer",
      "url": "https://wpackagist.org"
    },
    { // Tells Composer to look for our proprietary Awesome Plugin here.
        "url": "https://github.com/awesome-company/awesome-plugin.git",
        "type": "git"
    }
  ],
  "require": {
    "php": ">=5.5",
    "awesome-company/awesome-plugin": "dev-production", // Our plugin!
    "wpackagist-plugin/cool-plugin": "dev-trunk",       // Someone else' plugin
    "wpackagist-theme/cool-theme": "dev-trunk",         // Someone else' theme
    "composer/installers": "~1.2.0",     // Bedrock default
    "vlucas/phpdotenv": "^2.0.1",        // Bedrock default
    "johnpbloch/wordpress": "4.7.5",     // Bedrock default
    "oscarotero/env": "^1.0",            // Bedrock default
    "roots/wp-password-bcrypt": "1.0.0"  // Bedrock default
  },
  "extra": {
    // This is the magic that drops packages with the correct TYPE in the correct location. 
    "installer-paths": {
      "web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
      "web/app/plugins/{$name}/": ["type:wordpress-plugin"],
      "web/app/themes/{$name}/": ["type:wordpress-theme"]
    },
    "wordpress-install-dir": "web/wp"
  },
  "scripts": {
    "test": [
      "vendor/bin/phpcs"
    ]
  }
}

注1:JSONではコメントは合法ではありませんが、明確にするために上記のファイルに注釈を付けました。

注2:簡潔にするために、定型的なBedrockファイルの一部を切り取りました。

注3:これがtype、最初のcomposer.jsonファイルのフィールドが重要な理由です。Composerは自動的にweb/app/pluginsディレクトリにドロップします。


あなたの答えを感謝します、とても助かります!しかし、私はあなたが参照している「bootstrap.php」に興味があります。何が含まれていますか?:)
INT

1
bootstrap.phpファイルを持つことは、WPの内外でほとんどのプロジェクトで行う文体的なことです。私のブートストラップは通常、設定と環境変数をチェックするだけです。その主な目的は、プラグインがWP内から実行されたかスタンドアロンのPHPアプリとして実行されたかに関係なく、プラグインを常に実行する必要があるものにすることです。
haz

4

プラグインにはクラスの負荷があるため(一部にはTwigが含まれているため)オートロードを使用しますが、問題に気付かれたことはありません(プラグインのインストール> 20,000回)。

名前空間をサポートしないphpインストールを使用する必要がないと確信している場合は、問題ありません(現在のワードプレスブログの〜70%は名前空間をサポートしていません)。注意すべきいくつかの点:

名前空間は通常のphpでは大文字と小文字を区別しませんが、iisでfastcgi phpを使用している場合は覚えているようです。

また、現在開発中のコードが5.3.0以上でのみ使用されると確信している場合でも、その贅沢を持たないプロジェクトでコードを再利用することはできません。内部プロジェクトで使用されている名前空間。名前空間は、依存関係を削除しなければならないという頭痛の種と比較すると、それほど多くは追加さないことがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.