When I use spl_autoload_register in my plugin, I get:
Fatal error: Uncaught exception 'LogicException' with message
'Class wp_atom_server could not be loaded'
wp-includes\pluggable-deprecated.php on line 182
I did some reading and found various fixes. One on SO said not to use spl_autoload_register with WordPress.
Is that accurate?
I’m sure I can find a “fix” for the error, but I’m not sure I want to do that with each WP release.
If I do not use the autoload function, how should I be loading my classes? Here is what breaks now:
spl_autoload_extensions(".php");
spl_autoload_register();
use MyPluginClasses\Student as MS;
$student = new MS\Student();
echo $student->sayHello();
In student:
<?PHP
namespace MyPluginClasses\Student
{
class Student{
public function __Construct(){
echo "Hello Johnny";
}
public function sayHello(){
echo "Hello Johnny's Method";
}
}
}
This design works fine outside of WordPress.
I am really not sure if it’s good or bad practice to auto loading classes in WP plugin. For me, i see no side effects of using spl_autoload_register
(not tested performance)
So to answer your question, I would like to share a class from my upcoming plugin which i am using to auto load classes from a single directory without any issues and it does well for me so far.
/**
* 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();
To break this simple class in parts as you see i am using Singleton pattern. Constructor
is private and instance()
& $_instance
belongs to the pattern. Constructor has spl_autoload_register
function.
spl_autoload_register( array( $this, 'load' ) );
which is calling load
method from self class.
The first two lines from this method is:
$file = str_replace( '_', '-', strtolower( $class_name ) );
$file="class-" . $file;
which is pretty straight. if you follow WPCS it encourages you to follow a class naming convention prefixed with word class and then class name. ofcourse any underscore (_) is replaced with (-) dash.
so a file name of class WPSE_Post
would be class-wpse-post.php
Lower casing class names with strtolower
and using str_replace
to replace underscores with dashes. so WPSE_Post
now becomes wpse-post
. finally adding a prefix class-
on next line.
i am using is_readable
in conditional statement which is exchangeable with file_exists
. assuming YOUR_PLUGIN_PATH
is plugin’s base path and classes-dir
is under main plugin dir holding all of your classes that needs autoloading .
include_once
is used to load the actual file on call.
Usage:
you just need to include the above auto loader class in your plugin’s base file
/**
* Class autoloader.
*/
if ( ! class_exists( 'Annframe_Autoloader' ) ) {
include_once YOUR_PLUGIN_PATH/class-annframe-autoloader.php';
}
and then call your classes on demand.
new XYX_Class();
Another_Class::instance(); // etc
Note: I am not using namespace method in my solution so it may or may not fit according to your needs but posted here in hope that someone atleast get benefits of loading classes dynamically.