Проблемы с классами автоматической загрузки через регистр автоматической загрузки sp / возможно, мешающий автозагрузчику, специфичному для 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');

Теперь загрузчиком загружаются только мои собственные файлы классов плагинов, так как они являются единственными файлами, загруженными в предварительно определенную папку.

Однако, если три упомянутых класса WordPress все еще "отправляются" через мой класс autolaoder, правильно ли они (обычно) загружены WP? Или мой загрузчик конкурирует со встроенным загрузчиком WP? Как я могу это проверить? Или: Я делаю все эти вещи с автоматической загрузкой неправильно?

И почему эти три класса отправлены в мой загрузчик? Являются ли они единственными, которые будут загружены после загрузки плагинов?

Author: tfrommen, 2013-03-06

4 answers

В 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
Author: fuxia, 2014-08-21 20:10:54

Если у вас есть уникальное пространство имен для ваших классов, это работает. Я использую эту схему:

  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
Author: Ciantic, 2013-11-28 16:27:27

Теперь вы можете использовать плагин автозапуска WordPress. Он также поддерживает ваши собственные методы автоматической загрузки.

Пожалуйста, смотрите Страницу плагина WordPress для получения более подробной информации.

Правильное использование PHP __autoload может значительно сократить время загрузки сайта WP.

Пример вашей собственной функции __автозапуска проблематичен. У вас должна быть какая-то проверка, чтобы убедиться, что вы загружаете только свои собственные классы, чтобы избежать проблем.

Пожалуйста, обратите внимание, что если вы загружаете классы, его рекомендуется использовать require_once или i

 0
Author: D.A.H, 2013-09-19 18:37:32

На github есть простой и функциональный класс для автоматической загрузки с пространствами имен или без них: Классы автоматической загрузки в wordpress

 0
Author: user44321, 2019-08-16 08:08:27