I'm building a custom theme and I want to create a helper class for handling creation of metaboxes in admin panel. I have my class declared like this:

namespace ci\wp;

Metaboxes::init();

class Metaboxes {

    private static $instance;
    private static $post;

    private static $metaboxesPath = TEMPLATEPATH . "/config/metaboxes/";

    static function init() {
        global $post;
        self::$post = &$post;
        add_action( 'add_meta_boxes', [ __CLASS__, 'addMetabox' ], 10, 5 );
    }

    // ADD METABOX
    static function addMetabox($id, $title, $post_type, $position, $priority) {
        if (file_exists(self::$metaboxesPath.$id.'.php')) {
            require_once(self::$metaboxesPath.$id.'.php');
            add_meta_box($id, $title, 'do_'.$id, $post_type, $position, $priority);
        }
    }

[...]

The problem is that when I want to use the addMetabox method, by writing \ci\wp\Metaboxes::addMetabox('front_page_slide_settings', 'Slide settings', 'page', 'normal', 'high'); I get the following error:

Fatal error: Uncaught Error: Call to undefined function ci\wp\add_meta_box() in [...]

I tried several different methods of using add_action inside the class but no matter if it's a static class, singleton with add_action run at instantiation or a normal class with add_action in constructor, it always results in the said error.

Is there a way to make it work? What am I doing wrong?

  • 1
    As @birgire said you are calling the function before it's defined. Every add_meta_box function call should be hooked to the add_meta_boxes hook. You can either have an array with all desired metabox settings and then run a loop through the array, inside addMetabox that is hook to add_meta_boxes hook, and call add_meta_box with the settings as input or every time you call addMetabox you add an action. – Laxmana Apr 13 '17 at 10:56

You're actually calling the add_meta_box() function before it's defined, when you run this directly:

\ci\wp\Metaboxes::addMetabox(
    'front_page_slide_settings', 
    'Slide settings', 
    'page', 
    'normal', 
    'high'
);

You don't mention where you run it, but it's too early or you run it in the front-end, where add_meta_box() is not defined.

The add_meta_box() function is defined within this file:

/** WordPress Template Administration API */
require_once(ABSPATH . 'wp-admin/includes/template.php');

Make sure to run your problematic snippet afterwards, e.g. within the add_meta_boxes action, like you do within the Metaboxes::init() call.

The core init action, as an example, fires before that Template Administration API is loaded.

Thank you for help. I figure out exactly what I missed.

I simply forgot to wrap all calls to the addMetabox static method inside a function that is hooked to admin_init. After I did that, everything work as expected. I don't even need to hook to add_meta_boxes inside the Metaboxes class.


UPDATE: after spending some time figuring out how to quickly make other things like saving new post meta, it turned out that trying to simplify things like that using methods like that actually makes them more complicated. Adding metaboxes on admin_init hook makes it impossible to check edited post ID as at that moment the post var has no data. Lesson learned.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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