web-dev-qa-db-ja.com

Sp_autoload_registerを介したクラスの自動ロードに関する問題/その他WP固有の自動ローダーに干渉する

私はクラスをオートロードするために私が次のことをするプラグインに取り組んでいます:

function TFSLAutoload($class) {
    $classfile = dirname(__FILE__).'/includes/'.strtolower($class).'.php';
    include $classfile;
} // function TFSLAutoload
spl_autoload_register('TFSLAutoload');

プラグイン(クラス)では、クラスを定義するファイルをインクルード/要求せずに、クラスをインスタンス化(例:$myClassXYZ = new MyClassXYZ();)し、静的関数(例:MyClassXYZ::my_static_func();)を使用できます。つまり、すべてが期待通りに機能しています。

ただし、WP_DEBUGをtrueに設定すると、次のような警告が表示されます。

Warning: include(/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/wp_atom_server.php): failed to open stream: No such file or directory in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(): Failed opening '/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/wp_atom_server.php' for inclusion (include_path='.:') in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/Recursive_ArrayAccess.php): failed to open stream: No such file or directory in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(): Failed opening '/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/Recursive_ArrayAccess.php' for inclusion (include_path='.:') in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31
Warning: include(/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/WP_Session.php): failed to open stream: No such file or directory in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31 
Warning: include(): Failed opening '/var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/includes/WP_Session.php' for inclusion (include_path='.:') in /var/www/vhosts/MY-DOMAIN.TLD/wp-content/plugins/tf-song-list/tf-song-list.php on line 31

それから、ファイルが存在するかどうかを最初にチェックするようにオートロード機能を変更しました。

function TFSLAutoload($class) {
    $classfile = dirname(__FILE__).'/includes/'.strtolower($class).'.php';
    if (file_exists($classfile)) include $classfile;
    else echo "File »$classfile« does not exist.".PHP_EOL;
} // function TFSLAutoload
spl_autoload_register('TFSLAutoload');

これらのファイルは事前に定義されたフォルダに格納されている唯一のファイルであるため、今では私自身のプラグインクラスファイルのみがオートローダによってロードされます。

しかし、上記の3つのWordPressクラスがまだ私のautolaoderクラスを通して「送信」されている場合、それらは(実際には)WPによって正しくロードされることすらありますか?それとも、私のオートローダはWPの内蔵オートローダと競合していますか?どうすれば確認できますか?それともオートローディングのことを全部間違ったやり方でやってるの?

そして、なぜこれら3つのクラスが私のオートローダに送られるのですか?プラグインがロードされた後にロードされるのはそれらだけですか?

5
tfrommen

WordPressには組み込みのオートローダはありません。しかし、他のプラグインやテーマがオートローダを登録している可能性があり、実行順序に応じてこれらはあなたより早くまたは遅く呼び出されます。


更新21. 08. 2014 この答えは、私が推奨するものではなくなりました。必要ならオートローダを使ってください。


呼び出されたクラスがコードの責任の範囲内であることを確認する唯一の方法は、file_exists()を調べてクラス名をテストすることです。

file_exists()は遅く、その結果はファイルシステムによってキャッシュされるので、それに頼ることはできません。

オートローダを使用しないことをお勧めします 。代わりにプラグイン固有のクラスローダーを使用してください。

例:

/**
 * Load a class from /php/ directory.
 *
 * There is no file_exists() check to improve performance.
 *
 * @param  string  $class         Class name
 * @param  boolean $create_object Return an object or TRUE
 * @return bool|$class
 */
function t5_es_load_class( $class, $create_object = FALSE )
{
    // create the path base just once
    static $base = FALSE;

    ! $base && $base = plugin_dir_path( __FILE__ ) . 'php';
    ! class_exists( $class ) && require "$base/class.$class.php";

    return $create_object ? new $class : TRUE;
}

これで、この関数を使ってクラスを含めることができます。

t5_es_load_class( 'T5_Metabox_Base' );
$metabox = new T5_Metabox_Base( 'preview' );

…またはオブジェクトを作成する…

$data               = t5_es_load_class( 'T5_Property_List', TRUE );
$data->plugin_url   = plugin_dir_url( __FILE__ );
$data->plugin_path  = plugin_dir_path( __FILE__ );

より速く、より信頼性があり、より柔軟性があります。

4
fuxia

自分のクラスに固有の名前空間がある場合はそれが機能します。私はこのスキームを使います。

  1. すべてのクラスを名前空間に詰め込み、mypluginとしましょう(もちろん、myplugin\otherstuff\...のように、さらに名前空間があるかもしれません

  2. クラスをロードするオートローダを作成します - この名前空間でのみ 、あなたはこれを使用することができ、あなたのプラグインファイルの上にそれを置くことができます

    define("MYPLUGIN_DIR", plugin_dir_path(__FILE__));
    
    // Notice strlen(...) calls should be written as number for speed
    spl_autoload_register(function ($className) {           
        // Make sure the class included is in this plugins namespace
        if (substr($className, 0, strlen("myplugin\\")) === "myplugin\\") {
            // Remove myplugin namespace from the className
            // Replace \ with / which works as directory separator for further namespaces
            $classNameShort = str_replace("\\", "/", substr($className, strlen("myplugin\\")));
            include_once MYPLUGIN_DIR . "classes/$classNameShort.php";
        }
    });
    

それはそれです、あなたがそれぞれに異なる名前空間を持っていれば(そしてあなたはとにかくあなたはそうすべきです)複数のプラグインに対してうまく働きます。

5
Ciantic

あなたは今プラグインWordPressオートローダを使うことができます。それはあなた自身のオートロード方法もサポートします。

詳細は WordPressプラグインのページ をご覧ください。

PHP __autoloadを正しく使用すると、WPサイトの読み込み時間を大幅に短縮できます。

独自の__autoload関数のサンプルは問題があります。問題を回避するために、自分自身のクラスのみを確実にロードするように、何らかの検証を行う必要があります。

クラスをロードする場合、require_onceまたはiを使用することをお勧めします。

0
D.A.H

Githubには、名前空間の有無にかかわらず自動ロードするシンプルで機能的なクラスがあります。 wordpressのクラスを自動ロード

0
user44321