plugins - Problems with autoloading classes via sp_autoload_registermaybe interfering WP-specific autoloader

I'm working on a plugin in which I do the following for autoloading classes:function TFSLAutoload($class) {$classfi

I'm working on a plugin in which I do the following for autoloading classes:

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

In the plugin (classes) I can instantiate classes (e.g., use $myClassXYZ = new MyClassXYZ();) as well as use static functions (e.g., MyClassXYZ::my_static_func();) without including/requiring the file defining the very class. In short, everything is working as expected.

However, when having WP_DEBUG set to true, I do get the following warnings:

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

I then changed my autoload function to check first if the file exists:

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');

Now, only my own plugin class files are loaded by the autoloader, as they are the only files loacted in the pre-defined folder.

However, if the three mentioned WordPress classes are still being 'sent' through my autolaoder class, are they even(tually) loaded correctly by WP? Or is my autoloader competing with the built-in autoloader of WP? How can I check that? Or: Am I doing the whole autoloading stuff the wrong way?

And why are these three classes sent to my autoloader? Are they the only ones to be load after the plugins are loaded?

I'm working on a plugin in which I do the following for autoloading classes:

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

In the plugin (classes) I can instantiate classes (e.g., use $myClassXYZ = new MyClassXYZ();) as well as use static functions (e.g., MyClassXYZ::my_static_func();) without including/requiring the file defining the very class. In short, everything is working as expected.

However, when having WP_DEBUG set to true, I do get the following warnings:

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

I then changed my autoload function to check first if the file exists:

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');

Now, only my own plugin class files are loaded by the autoloader, as they are the only files loacted in the pre-defined folder.

However, if the three mentioned WordPress classes are still being 'sent' through my autolaoder class, are they even(tually) loaded correctly by WP? Or is my autoloader competing with the built-in autoloader of WP? How can I check that? Or: Am I doing the whole autoloading stuff the wrong way?

And why are these three classes sent to my autoloader? Are they the only ones to be load after the plugins are loaded?

Share Improve this question edited Dec 17, 2013 at 12:00 tfrommen asked Mar 6, 2013 at 12:44 tfrommentfrommen 9,2317 gold badges40 silver badges59 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 4

There is no built-in autoloader in WordPress. But other plugins or a theme might have registered an autoloader, and depending on the order of execution these are called earlier or later than yours.


Update 21. 08. 2014 This answer is no longer what I would recommend. Do use an autoloader if you need one.


The only way to make sure the called class is in your code’s responsibility is checking with file_exists() and testing the class name.

file_exists() is slow and its result is cached by the file system, so you cannot rely on it anyway.

I recommend not to use an autoloader. Use a plugin specific class loader instead.

Example:

/**
 * 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;
}

Now you can use this function either to just include the class …

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

… or create an object …

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

Faster, more reliable, more flexible.

If you have unique namespace for your classes it works. I use this scheme:

  1. Stuff all your classes in namespace, let's say myplugin (you may have further namespaces of course, like myplugin\otherstuff\...

  2. Create autoloader that loads classes only in this namespace, you can can use this, put it on top of your plugin file:

    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";
        }
    });
    

That's it, it works fine for multiple plugins if you have different namespace for each (and you should anyway).

You can use a plugin WordPress Autoloader now. It supports also your own autoload methods.

Please see WordPress Plugin page for more details.

Proper usage of PHP __autoload can dramatically reduce WP site load time.

Sample of your own __autoload function is problematic. You should have some sort validation, to make sure that you load your own classes only, to avoid problems.

Please note, that if you load classes, its reccomended to use require_once or i

There is a simple and fonctionnal class on github to autoload with or without namespaces : Autoload classes in wordpress

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745237925a4618001.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信