Autoloading is the process of automatically loading and namespace PHP classes without explicitly loading them with the require(), require_once(), include().
Autoloading: A class autoloader is a mechanism for loading uninstantiated classes and the files that contain them automatically. You may safely use any class without explicitly including the file if you utilize a well-established file name scheme and a standard autoloader.
I’ve been using this loader on a few projects. First checks to see if the class is in the current autoloading and namespace, then exit if it isn’t. It’s only a matter of string manipulation from there to get the class.
<?php
spl_autoload_register(__NAMESPACE__ . '\autoload');
function autoload($cls)
{
$cls = ltrim($cls, '\');
if(strpos($cls, __NAMESPACE__) !== 0)
return;
$cls = str_replace(__NAMESPACE__, '', $cls);
$path = PLUGIN_PATH_PATH . 'inc' .
str_replace('\', DIRECTORY_SEPARATOR, $cls) . '.php';
require_once($path);
}
?>
This might simply be adapted to work without namespaces. You may just test for that prefix if you prefix your plugin/classes theme’s uniformly.
Then, in the class name, use underscores to serve as directory separators. You’ll probably want to utilize a class-map autoloader if you’re utilizing a lot of classes.
Namespaces and Hooks
The call_user_func (and call_user_func_array) function in WordPress’ hooks system take function names as strings and call them when they do_action(and, subsequently, call_user_func) function call is performed.
When using namespaces, this involves passing fully qualified function names into hooks that contain the namespace
<?php
namespace WPSESomeNameSpace;
add_filter('some_filter', 'WPSE\SomeNameSpace\the_function');
function the_function()
{
return 'did stuff';
}
?>
If you wish to achieve this, you should definitely make extensive use of the __NAMESPACE__
magic constant.
<?php
namespace WPSESomeNameSpace;
add_filter('some_filter', __NAMESPACE__ . '\the_function');
function the_function()
{
return 'did stuff';
}
?>
It’s easier if you always place your hooks inside classes. All hooks in the function Object() using $this and the conventional create instance of a class work well.
<?php
namespace WPSESomeNameSpace;
new Plugin;
class Plugin
{
function __construct()
{
add_action('plugins_loaded', array($this, 'loaded'));
}
function loaded()
{
// this works!
}
}
?>
If you wish to use static methods as I do, the first parameter in the array must be the fully qualified class name. Because it would be a lot of effort you may just use the __CLASS__
constant or get class.
<?php
namespace WPSESomeNameSpace;
Plugin::init();
class Plugin
{
public static function init()
{
add_action('plugins_loaded', array(__CLASS__, 'loaded'));
// OR: add_action('plugins_loaded', array(get_class(), 'loaded'));
}
public static function loaded()
{
// this works!
}
}
?>
Using Core Classes
The resolution of class names in PHP is a little strange. Use
statements are required if you want to use basic WP classes (such as WP_Widget
in the example below).
use - WP_Widget;
<?php
class MyWidget extends WP_Widget
{
// ...
}
?>
Or you can use the fully qualified class name — basically just prefixing it with a backslash.
<?php
namespace WPSESomeNameSpace;
class MyWidget extends WP_Widget
{
// ...
}
?>
Defines
You might wish to indicate stuff like the path to your plugin, which you’ll use frequently. Unless you specifically specify the namespace as the first parameter of define, everything is put in the root namespace when you use the define statement.
<?php
namespace WPSESomeNameSpace;
// root namespace
define('WPSE_63668_PATH', plugin_dir_path(__FILE__));
// in the current namespace
define(__NAMESPACE__ . '\PATH', plugin_dir_path(__FILE__));
?>
With PHP 5.3 +, you may also utilize the const keyword in the root level of a file.Costs remain in the current namespace at all times, but they are less versatile than defined calls.
<?php
namespace WPSESomeNameSpace;
// in the current namespace
const MY_CONST = 1;
// this won't work!
const MY_PATH = plugin_dir_path(__FILE__);
?>