Reputation: 852
I have been learning about namespaces and autoloading for my latest Wordpress plugin.
I am having an issue working out if it is possible to use an autoloader to statically instantiate classes too.
What I have done so far
I have added this autoloader to my plugin file:
spl_autoload_register( 'bnfoAutoload' );
function bnfoAutoload( $class ) {
// project-specific namespace prefix
$prefix = 'BnfoAutoload\\';
// base directory for the namespace prefix
$base_dir = __DIR__ . '/';
// does the class use the namespace prefix?
$len = strlen( $prefix );
if ( strncmp( $prefix, $class, $len ) !== 0 ) {
// no, move to the next registered autoloader
return;
}
// get the relative class name
$relative_class = substr( $class, $len );
// replace the namespace prefix with the base directory, replace namespace
// separators with directory separators in the relative class name, append
// with .php
$file = $base_dir . str_replace( '\\', '/', $relative_class ) . '.php';
// if the file exists, require it
if ( file_exists( $file ) ) {
require $file;
}
}
I have got autoloading to work effectively for newly instanstiated instances of a class e.g.:
$response = new BnfoAutoload\Includes\Tester();
$exact_response = $response->testFunction();
and through reading this SO post when calling static methods e.g.
BnfoAutoload\Includes\Tester::testStaticFunction()
Context
However, occasionally I want to statically instantiate a class, for example if I want to add a filter.
e.g. this would be 'classfile.php';
namespace BnfoAutoload\Includes\
class LoadClass {
public function __construct() {
add_action( 'wp_head', [ $this, 'loadFunction' ];
}
public function loadFunction() {
// something
}
}
new LoadClass();
Potential solutions
Option 1: I can manually require classfile.php in my plugin file, which would then statically instantiate the class.
require_once ('classfile.php' );
Option 2: I can instantiate these static classes in the plugin file, at which point they are picked up by the autoloader
new BnfoAutoload\Includes\LoadClass();
I am not sure if either of these is correct so any alternative thoughts much appreciated.
Upvotes: 0
Views: 157
Reputation: 569
You're confusing yourself a little bit. You can't instatiate a static class, you can only use a static method or property. To instantiate it, means it's not static.
In anycase, static methods in PHP are a design smell. Now let me put a cavet here, they aren't useless. If you raise you hand and say: "I need a globally namespaced fucntion that shares a global system state", [i.e. your class is designed to be used by OTHER plugins in the global space] then static OOP methods are the way to go. If you don't understand why you would require a globally namespaced function, especially why you WOULDNT want that in WordPress, take the advice of experienced coders and DON'T EVER USE STATIC METHODS IN PHP - ESPECIALLY IN WORDPRESS!
Now as to WordPress, you specifically couldn't use a static class this way. Consider what is happening in this scenario:
add_action('init', array(new someClass, 'someMethod'));
When WordPress gets to the "init" action in the event driven stack, it creates the memory object "someClass" and passes it to the init hook. The thing that is passes is the instatiated object. [Sure it could be a design feature to pass a pointer to the static method, it's just not how WordPress works].
Anyway, to sum up, NEVER EVER EVER use static methods in WordPress. WordPress uses globals because it's a legacy application. Don't make it WORSE.
**** EDIT **** Ok, so I still say you should never use statics in WordPress because they are hard to test. However you CAN call a static method by putting the action call within the class like this, from developer.wordpress.org :
/**
* Class WP_Docs_Static_Class.
*/
class WP_Docs_Static_Class {
/**
* Initializer for setting up action handler
*/
public static function init() {
add_action( 'save_post', array( get_called_class(), 'wpdocs_save_posts' ) );
}
/**
* Handler for saving post data.
*/
public static function wpdocs_save_posts() {
// do stuff here...
}
}
WP_Docs_Static_Class::init();
Upvotes: 1