Должен ли я использовать spl_autoload_register () в моем плагине?

11

Когда я использую spl_autoload_register в моем плагине, я получаю:

    Fatal error: Uncaught exception 'LogicException' with message
   'Class wp_atom_server could not be loaded'

    wp-includes\pluggable-deprecated.php on line 182

Я немного почитал и нашел различные исправления. Один на SO сказал не использовать spl_autoload_register с WordPress.

Это точно?

Я уверен, что смогу найти «исправление» для ошибки, но я не уверен, что хочу делать это с каждым выпуском WP.

Если я не использую функцию автозагрузки, как мне загружать свои классы? Вот что ломается сейчас:

spl_autoload_extensions(".php");
spl_autoload_register();

use MyPluginClasses\Student as MS;

$student = new MS\Student();

echo $student->sayHello();

У студента:

<?PHP
namespace MyPluginClasses\Student
{
    class Student{
        public function __Construct(){
            echo "Hello Johnny";
        }
        public function sayHello(){
            echo "Hello Johnny's Method";

        }

    }
}

Этот дизайн прекрасно работает вне WordPress.

Джонни
источник
4
Я обновил свой ответ . Если вы все сделаете правильно - с помощью функции обратного вызова - вы можете использовать spl_autoload_register()без негативных побочных эффектов.
fuxia
1
@toscho Ваш код все еще лучший способ сделать автозагрузку в WP?
Джонни
Нет. Самый быстрый способ - попасть glob()в каталог один раз, а затем доставить классы, когда они необходимы spl_autoload_register().
fuxia
1
Я напишу ответ позже, показывая наше текущее (еще не опубликованное) решение от Multilingual Press.
fuxia

Ответы:

1

Я действительно не уверен, хорошо ли это или плохо делать автоматическую загрузку классов в плагине WP. Для меня я не вижу никаких побочных эффектов использования spl_autoload_register(не проверенная производительность)

Поэтому, чтобы ответить на ваш вопрос, я хотел бы поделиться с классом из моего предстоящего плагина, который я использую для автоматической загрузки классов из одного каталога без каких-либо проблем, и это пока хорошо для меня.

/**
 * Annframe Class Autoloader.
 *
 * @package Annframe
 * @since 0.1.0
 */
class Annframe_Autoloader {
    /**
     * Singleton.
     *
     * @since 0.1.0
     * @var Annframe_Autoloader - Single instance.
     */
    private static $_instance = null;

    /**
     * Private Construct.
     *
     * @package Annframe
     * @since 0.1.0
     */
    private function __construct() {
        spl_autoload_register( array( $this, 'load' ) );
    }

    /**
     * Singleton method.
     *
     * @package Annframe
     * @since 0.1.0
     */
    public static function _instance() {
        if ( ! self::$_instance ) {
            self::$_instance = new Annframe_Autoloader();
        }
        return self::$_instance;
    }

    /**
     * Class Loader.
     *
     * @package Annframe
     * @since 0.1.0
     *
     * @param string $class_name - Class name to load.
     * @return null - Do not return anything.
     */
    public function load( $class_name ) {
        $file = str_replace( '_', '-', strtolower( $class_name ) );
        $file = 'class-' . $file;
        if ( is_readable( trailingslashit( YOUR_PLUGIN_PATH. '/classes-dir' ) . $file . '.php' ) ) {
            include_once trailingslashit( YOUR_PLUGIN_PATH. '/classes-dir' ) . $file . '.php';
        }
        return;
    }
}

Annframe_Autoloader::_instance();

Чтобы разбить этот простой класс на части, как вы видите, я использую шаблон Singleton. Constructorявляется приватным и instance()& $_instanceотносится к образцу. Конструктор имеет spl_autoload_registerфункцию.

spl_autoload_register( array( $this, 'load' ) );

который вызывает loadметод из собственного класса. Первые две строки этого метода:

$file = str_replace( '_', '-', strtolower( $class_name ) );
$file = 'class-' . $file;

что довольно прямо. если вы следуете WPCS, это побуждает вас следовать соглашению об именах классов с префиксом word class и затем class name. Конечно, любое подчеркивание (_) заменяется на (-) тире.

поэтому имя файла класса WPSE_Postбудетclass-wpse-post.php

Имена классов в нижнем регистре с strtolowerи используют str_replaceдля замены подчеркивания тире. так WPSE_Postтеперь и становится wpse-post. наконец добавив префикс class-на следующей строке.

Я использую is_readableв условном заявлении, которое можно обменять с file_exists. предполагая, YOUR_PLUGIN_PATHчто это базовый путь плагина и classes-dirнаходится в директории основного плагина, содержащей все ваши классы, которые требуют автозагрузки.

include_once используется для загрузки актуального файла по вызову.

Использование:

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

/**
 * Class autoloader.
 */
if ( ! class_exists( 'Annframe_Autoloader' ) ) {
    include_once YOUR_PLUGIN_PATH/class-annframe-autoloader.php';
}

а затем позвоните в ваши классы по требованию.

new XYX_Class();
Another_Class::instance(); // etc

Примечание. Я не использую метод пространства имен в своем решении, поэтому он может подходить или не соответствовать вашим потребностям, но размещен здесь в надежде, что кто-то хотя бы получит преимущества от загрузки классов динамически.

Anwer AR
источник
-1
    function MyPluginClasses_autoloader( $class_name ) {
  if ( false !== strpos( $class_name, 'MyPluginClasses' ) ) {
    $parts = explode('\\', $class_name);
    require_once RoothPath . DIRECTORY_SEPARATOR .'lib'.DIRECTORY_SEPARATOR.end($parts) . '.php';
  }
}
spl_autoload_register( 'MyPluginClasses_autoloader' );
use MyPluginClasses\Student as MS;
$student = new MS\Student();
echo $student->sayHello();
Мелдин Ксавье
источник
2
Хотя размещение кода хорошо, вы должны объяснить, как и почему это отвечает на вопрос.
Лаксмана
1
поскольку ваш плагин не единственный плагин в системе, код, который просто загружает классы, не проверив сначала, что они ваши, рано или поздно создаст проблемы, пытаясь загрузить неправильный файл для класса, объявленного в другом плагине.
Марк Каплун