Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I am writing a class to create metaboxes and save the form data. The problem is, I keep getting a warning when I click "publish":

Warning: call_user_func_array() expects parameter 1 to be a valid callback, function Mighty_Metabox not found or invalid function name"

Some of the things I know: The meta box shows on page load. The save function is called on page load. The warning above is returned on publish. The save function is not called on publish.

Do I need to put the save_post action hook somewhere else? Am I getting the wordpress integration into my class completely wrong? Some help on how and when to call methods like the save method would be greatly appreciated:

    if (is_admin()){
    add_action('load-post.php', 'Mighty_Metabox');
}

//the class
class Mighty_Metabox{

    //the vars
    public $id = false;
    public $title = false;
    public $callback = array();
    public $post_type = array();
    public $context = false;
    public $priority = false;
    public $callback_args = array();
    public $template = false;

    public function __construct($params=false){
        if($params){
            //arrange params as key => value pairs
            foreach($params as $key => $value){
                $this->{$key} = $value;
            }

            //if admin page, add the action - add (metabox)
            if(is_admin){
                //set the callback to create metabox
                $this->callback = array($this, '_create');

                //add the add metabox action
                add_action('add_meta_boxes', array($this, '_add'));

                //add the save metabox action
                add_action('save_post', array($this,'_save'));

            }
        }
    }

    function _add(){
        //add the metabox with user set params
        add_meta_box($this->id, $this->title,  $this->callback, $this->post_type, $this->context, $this->priority, $this->callback_args);

    }

    function _create(){
        //create the metabox            
        include($this->template);
        // create a nonce for verification
        echo '<input type="hidden" name="'. $this->id .'_nonce" value="' . wp_create_nonce($this->id) . '" />';
    }

    function _save(){
        // verify if this is an auto save routine. 
        // If it is our form has not been submitted, so we dont want to do anything
        if (defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE) {
            return;
        }

        // verify this came from the our screen and with proper authorization,
        // because save_post can be triggered at other times
        $nonce = isset($_POST[$this->id.'_nonce']) ? $_POST[$this->id.'_nonce'] : NULL;
        if (!wp_verify_nonce($nonce, $this->id)){
            return $post_id;
        }

        $this->_debug(false); // won't get here on page load
    }

    private function _debug($exit=true){
        var_dump(debug_backtrace());
        return ($exit)? exit(): false;
    }
}

And here is the use:

$args = array
(
    'id' => '_subtitle',
    'title' => 'Subtitle',
    'post_type' => 'post',
    'context' => 'normal',
    'priority' => 'high',
    'template' => 'subtitle.php'
);

//subtitle metabox
$subtitle_mb = new Mighty_Metabox($args);

FYI: I am fairly new to OOP programming. I have been looking at the codex for metaboxes in order to learn more, but their class just seems like a wrapper for some code and doesn't seem to allow you to instantiate it - I may be wrong in thinking this.

EDIT: Here is the subtitle.php file that is being included:

<div class="my_meta_control">

<table class='metabox'>

    <tr>
        <th valign='top'><label>Subtitle</label></th>
        <td>
            <input type="text" id="<?php echo $this->id; ?>" name="<?php echo $this->id; ?>" value="" class='large-text' /><br />
            <span class='description'>The subtitle will appear under the main post or page title.</span>
        </td>
    </tr>

</table>

share|improve this question
    
What is the code in subtitle.php file? –  Vinod Dalvi Feb 28 '13 at 11:13
    
@VinodDalvi I have updated the question to contain the subtitle.php code. Thanks. –  Danny Feb 28 '13 at 11:31
add comment

1 Answer 1

I have modified your code as following and it is working for me. I have removed the constructor from your code and added the code in method and called that method using object.

if (is_admin()){
add_action('load-post.php',  array('Mighty_Metabox' , 'Custom_Mighty_Metabox'));
}

//the class
class Mighty_Metabox{

//the vars
public $id = false;
public $title = false;
public $callback = array();
public $post_type = array();
public $context = false;
public $priority = false;
public $callback_args = array();
public $template = false;



public function Custom_Mighty_Metabox($params=false){
    if($params){
        //arrange params as key => value pairs
        foreach($params as $key => $value){
            $this->{$key} = $value;
        }

        //if admin page, add the action - add (metabox)
        if(is_admin){
            //set the callback to create metabox
            $this->callback = array($this, '_create');

            //add the add metabox action
            add_action('add_meta_boxes', array($this, '_add'));

            //add the save metabox action
            add_action('save_post', array($this,'_save'));

        }
    }
}

function _add(){
    //add the metabox with user set params
    add_meta_box($this->id, $this->title,  $this->callback, $this->post_type, $this->context, $this->priority, $this->callback_args);

}

function _create(){
    //create the metabox            
    include($this->template);
    // create a nonce for verification
    echo '<input type="hidden" name="'. $this->id .'_nonce" value="' . wp_create_nonce($this->id) . '" />';
}

function _save(){
    // verify if this is an auto save routine. 
    // If it is our form has not been submitted, so we dont want to do anything
    if (defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE) {
        return;
    }

    // verify this came from the our screen and with proper authorization,
    // because save_post can be triggered at other times
    $nonce = isset($_POST[$this->id.'_nonce']) ? $_POST[$this->id.'_nonce'] : NULL;
    if (!wp_verify_nonce($nonce, $this->id)){
        return $post_id;
    }

    $this->_debug(false); // won't get here on page load
}

private function _debug($exit=true){
   // var_dump(debug_backtrace());
    return ($exit)? exit(): false;
}
}

$args = array
(
'id' => '_subtitle',
'title' => 'Subtitle',
'post_type' => 'post',
'context' => 'normal',
'priority' => 'high',
'template' => 'subtitle.php'
);

//subtitle metabox
$subtitle_mb = new Mighty_Metabox();
$subtitle_mb->Custom_Mighty_Metabox($args);
share|improve this answer
    
That seems to have done it! Thank you very much. So, how come my constructor method wouldn't work? I thought it was good OOP PHP practice to use one the way I did. But your way works, so I can't complain! Now I just need to learn about the rest of the save_post functionality! –  Danny Feb 28 '13 at 12:37
    
I think I was a bit quick to check this as the answer, it has solved half of the issue - the error is no longer displayed. But the _save method does not get called when publish is clicked. Any idea's? –  Danny Feb 28 '13 at 13:37
    
I have checked it and it is getting called. You can check it by adding this code in _save method : echo '_save gets called'; exit(); –  Vinod Dalvi Mar 1 '13 at 4:22
    
Correct me if I'm wrong, but the '_save' method is meant to be called on page load - which is working - and what I believe you are referring to. However it does not get called when 'publish' is clicked, therefore no attempt to save metadata can be made in the '_save' method. –  Danny Mar 1 '13 at 10:06
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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