11

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.

4
  • 4
    I have updated my answer. If you do it right – with a callback function – you can use spl_autoload_register() without negative side-effects. – fuxia Aug 21 '14 at 20:12
  • 1
    @toscho Is your code still the best way to do autoloading in WP? – johnny Aug 22 '14 at 13:00
  • No, it is not. The fastest way is to glob() the directory once, then deliver the classes when they are needed per spl_autoload_register(). – fuxia Aug 22 '14 at 13:02
  • 1
    I will write an answer later, showing our current (not yet published) solution from Multilingual Press. – fuxia Aug 22 '14 at 13:08
1

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.

-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
  • 2
    Although posting code is good you should explain how and why this answer the question. – Laxmana Feb 22 '17 at 9:37
  • 1
    as your plugin is not the only plugin in the system, code that just loads classes without verifying first that they are yours, is going to create trouble sooner or later by trying to load the wrong file for a class declared in another plugin. – Mark Kaplun Jan 3 '18 at 3:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.