我正在开发一个插件,我在其中为自动加载类执行以下操作:
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\');
现在,autoloader只加载我自己的插件类文件,因为它们是预定义文件夹中唯一的文件。
然而,如果上述三个WordPress类仍然通过我的Autolaorder类“发送”,那么WP是否(实际上)正确加载了它们?还是我的自动加载器与WP的内置自动加载器竞争?我如何检查?或者:我是否以错误的方式进行了整个自动加载?
为什么这三门课要送到我的自动加载器?它们是加载插件后唯一要加载的吗?
最合适的回答,由SO网友:fuxia 整理而成
WordPress中没有内置自动加载器。但是其他插件或主题可能已经注册了自动加载器,根据执行顺序,这些插件或主题的调用时间可能早于或晚于您的插件或主题。
<小时>Update 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__ );
更快、更可靠、更灵活。
SO网友:Ciantic
如果您的类有唯一的名称空间,它就可以工作。我使用此方案:
比方说,在名称空间中填充所有类myplugin
(当然,您可能还有更多的名称空间,如myplugin\\otherstuff\\...
创建仅在此命名空间中加载类的自动加载程序,您可以使用它,将其放在插件文件的顶部:
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";
}
});
就是这样,如果每个插件都有不同的名称空间,那么它可以很好地用于多个插件(无论如何,您应该这样做)。