我应该在插件中使用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

我做了一些阅读,发现了各种修复方法。 有人说不要在WordPress中使用spl_autoload_register。

准确吗?

我确定我可以找到该错误的“修复程序”,但是我不确定我想在每个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中自动加载的最佳方法吗?
约翰尼2014年

不它不是。最快的方法是glob()一次到目录,然后在需要时交付类spl_autoload_register()
fuxia

1
稍后,我将写一个答案,显示Multilingual Press当前(尚未发布)的解决方案。
fuxia

Answers:


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,则鼓励您遵循以单词class和类名为前缀的类命名约定。当然,所有下划线(_)都用(-)破折号代替。

如此类的文件名WPSE_Postclass-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

注意:我未在解决方案中使用名称空间方法,因此它可能符合或可能不符合您的需求,但在此处发布,希望有人至少能从动态加载类中受益。


-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
尽管发布代码很好,但是您应该解释如何以及为什么这样做可以回答问题。
Laxmana'2

1
由于您的插件不是系统中唯一的插件,因此仅在不首先验证它们是否属于您的情况下加载类的代码将通过尝试为另一个插件中声明的类加载错误的文件而早晚造成麻烦。
马克·卡普伦'18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.