Implementing namespaces in plugin template

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 Answers
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!';
    }
}

Leave a Comment