3

To get with the time and improve my coding practices, I'm starting to implementing namespaces in my own plugins moving forward since there are some advantages, such as eliminating ambiguity.

I found a similar question to help me set up my plugin template which worked for me. However, I've since modified it slightly. This is my setup:

In wp-plugin-template/wp-plugin-template.php:

<?php
/**
 * Plugin Name: WP Plugin Template
 */
# If accessed directly, exit
if ( ! defined( 'ABSPATH' ) ) exit;
# Call the autoloader
require_once( 'autoloader.php' );

use PluginTemplate\admin\Plugin_Meta;
new Plugin_Meta;

In wp-plugin-template/autoloader.php:

<?php
spl_autoload_register( 'autoload_function' );
function autoload_function( $classname ) {
    $class = str_replace( '\\', DIRECTORY_SEPARATOR, str_replace( '_', '-', strtolower($classname) ) );
    # Create the actual file-path
    $path = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $class . '.php';
    # Check if the file exists
    if ( file_exists( $path ) ) {
        # Require once on the file
        require_once $path;
    }
}

In wp-plugin-template/admin/plugin-meta.php:

<?php
namespace PluginTemplate\admin;
class Plugin_Meta {
    public function __construct() {
        add_action( 'plugins_loaded', array($this, 'test' ) );
    }

    public function test() {
        echo 'It works!';
    }
}

When I try to activate the plugin template for testing, I get the following error:

Fatal error: Class PluginTemplate\admin\Plugin_Meta not found in wp-content/plugins/wp-plugin-template/wp-plugin-template.php on line 11

In this case, line 11 is:

new Plugin_Meta;

I think this is due to me having the namespace named PluginTemplate? What am I doing wrong? Just to reiterate, the previous question that I mentioned worked for me before I started to rename my files and directories.

2

The problem is with your Autoloader set-up. You need to convert your Camelcase namespacese to dashes for locating files as per your current folder structure.

I have added convert function and updated your autoloader function.

In wp-plugin-template/autoloader.php:

<?php
spl_autoload_register( 'autoload_function' );
function autoload_function( $classname ) {
    $class = str_replace( '\\', DIRECTORY_SEPARATOR, str_replace( '_', '-', strtolower(convert($classname)) ) );
    # Create the actual file-path
    $path = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $class . '.php';
    # Check if the file exists
    if ( file_exists( $path ) ) {
        # Require once on the file
        require_once $path;
    }
}

function convert($class){
    $class = preg_replace('#([A-Z\d]+)([A-Z][a-z])#','\1_\2', $class);
    $class = preg_replace('#([a-z\d])([A-Z])#', '\1_\2', $class);
    return $class;
}

Also you have to update your top level namespace to WpPluginTemplate in both wp-plugin-template.php and admin/plugin-meta.php as you are using wp-plugin-template as your plugin folder name.

UPDATE:

When autoloader tries to find Plugin_Meta class, it will look into YOUR_PLUGIN_DIR/wp-plugin-template/admin/plugin-meta.php

In wp-plugin-template.php

<?php
/**
 * Plugin Name: WP Plugin Template
 */
# If accessed directly, exit
if ( ! defined( 'ABSPATH' ) ) exit;
# Call the autoloader
require_once( 'autoloader.php' );

use WpPluginTemplate\admin\Plugin_Meta;
new Plugin_Meta;

In wp-plugin-template/admin/plugin-meta.php

<?php
namespace WpPluginTemplate\admin;
class Plugin_Meta {
    public function __construct() {
        add_action( 'plugins_loaded', array($this, 'test' ) );
    }

    public function test() {
        echo 'It works!';
    }
}
|improve this answer|||||
  • I see. So it's the autoloader. I think what's throwing it off is that my plugin folder has dashes (wp-plugin-template) whereas the one from the example doesn't (oowp). I updated my autoloader to the code that you provides and the namespaces to WpPluginTemplate, but I still get the same error. What am I doing wrong? – Ethan Jinks O'Sullivan Oct 2 '16 at 19:23
  • check code edits.I added all files with update. Make sure you use exact same code as I pasted, I have tested this on WP install and plugin is activated, No Errors. Key is using correct namesapces. If still throws error try to echo path autholoader uses to look for your included files. – C Sabhar Oct 2 '16 at 19:48
  • Thanks for the update. I see why it didn't work for me with your initial answer, I also replaced WP_PLUGIN_DIR with plugin_dir_path( __FILE__ ) from @birgire's answer. – Ethan Jinks O'Sullivan Oct 2 '16 at 19:59
1

Just some additional note about your autoloader:

If the $classname input is PluginTemplate\admin\Plugin_Meta then the $path becomes

/full/path/to/wp-content/plugins/plugintemplate/admin/plugin-meta.php

and this file doesn't exists and the Plugin_Meta class definition isn't loaded.

It's also not recommended to use the WP_PLUGIN_DIR constant directly, there are alternatives, like plugin_dir_path( __FILE__ ).

There are more complete autoloaders out there, e.g. the generated autoloader in Composer.

|improve this answer|||||
  • Thanks for clarifying. That makes much more sense when you lay it out that way. I used your alternative of plugin_dir_path( __FILE__ ) along with @CSabhar's answer, but it seems to not work unless I use WP_PLUGIN_DIR instead. Why's that? Also, I checked out the link that you provided, but I don't entirely understand how to generate the autoloader using Composer since I don't have any experience using it. May you please elaborate? – Ethan Jinks O'Sullivan Oct 2 '16 at 20:09
  • I think if $path = plugin_dir_path( __FILE__ ) . $class . '.php'; in your example and if you move admin/ under the plugintemplate/ directory, then your simple autoloader should work. One can map the class names to the directory structure, in various ways. There are some standards like the PSR-4. With Composer, one can define it in the composer.json file. There are some examples here. @EthanJinksO'Sullivan – birgire Oct 2 '16 at 20:32

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.