1

I have a quite complex PHP class, reponsible for creating and printing meta_boxes, generating and saving meta fields, ...

Each meta_box (object of class) has its own save function, that updates meta data of post (fields for them are instances of another class) as well as its post_excerpt and post_content. Yep, it's probably a little complicated, but as I'm only starting with OOP, I'm pretty happy with it so far.

TL;DR, THE PROBLEM: With wp_update_post() called on save_post hook, I get an infinite loop. This issue is documented on WP codex as well as mentioned here on WPSE: How to avoid infinite loop in save_post callback.

If you are calling a function such as wp_update_post that includes the save_post hook, your hooked function will create an infinite loop. To avoid this, unhook your function before calling the function you need, then re-hook it afterward.

Source: Codex

This is a very simplified version of a code I am using:

class MetaBox {

    public function __construct() {
        // a lot of stuff, hooks and other function initiations
        add_action('save_post',array($this,'save_box'), 20);
    }

    // more stuff

    function save_box() {
        // verify nonces, bail out on autosave, ajax, cron, ...

        switch ($this->id) {
            case 'editor':
            case 'postexcerpt':

                // remove action
                remove_action('save_post', array($this,'save_box'));
                // bail out on post_revision
                if (!wp_is_post_revision($post_id) ){

                    $post = array(
                        // post id
                        'id'    => $post_id,
                        // tosave: either post_content or post_excerpt
                        // value: pulled from static associative multi-array inside MetaBox
                        $tosave => self::$meta[$this->id][$this->id]
                    );
                    wp_update_post($post);          
                }

                // add action back  
                add_action('save_post', array($this, 'save_box'));

            break;
            default:
                // some saving functionality for meta values, that WORKS just fine
            break;
        }
    }
}

I am getting an infinite loop with PHP error notice: Undefined index: ID in XXX/web/wp-includes/post.php on line 2987

Am I removing/adding save hook wrong? Does it have something in common with using the save function non-statically?

I am of course happy to provide the rest of the relevant code, if there's no apparent problem with this structure.

EDIT

The infinite loop problem is gone - as @TheDeadMedic mentioned, problem lied at not matching priority.

To remove a hook, the $function_to_remove and $priority arguments must match when the hook was added. This goes for both filters and actions. No warning will be given on removal failure.

Codex: http://codex.wordpress.org/Function_Reference/remove_action

EDIT 2

As PHP is a case sensitive language, Undefined index ID notice problem lied in my $post array (parameter of wp_update_meta). The ID key must be specified uppercase.

$post = array(
    'ID' => $post_id    // ID must be uppercase
)

/////

As my question turned out to be very localized, feel free to delete it. And thanks again for helping me!

Thanks in advance!

  • Do the following: var_dump( $GLOBALS['wp_filters'][ current_filter() ] ); right before and right after your call to remove_action(). Then search this site for remove_action() explanations. :) – kaiser Feb 19 '14 at 16:06
  • @kaiser: Thanks for letting me know! However the var_dump echoes NULL and few errors: - Undefined index: wp_filters - Cannot modify header information - headers already sent by Should this be happening? Thanks again! – Petr Cibulka Feb 19 '14 at 16:48
  • Sorry, it's wp_filter without the s at the end. – kaiser Feb 19 '14 at 16:53
  • @kaiser: Tried that, as I still have a lot to learn about Wordpress hooks and filters. Although, as the infinite loop problem is gone, is the Undefined index: ID [...] /wp-includes/post.php on line 2987 related to hooks/filters as well? Should I be digging there? – Petr Cibulka Feb 19 '14 at 17:08
  • Look at the XDebug output/backtrace. The error occurs somewhere where you're trying to access that array keys value - which apparently isn't set. Could mean no result, etc. Could imagine that it's from your self::$meta[] call. Anyway, you'll have to get the basics of empty/isset/etc to grasp what this is about (see php.net) and have XDebug or similar in your local dev stack to backtrace that. – kaiser Feb 19 '14 at 17:16
6

You need to match the $priority you used to hook the action:

remove_action( 'save_post', array( $this, 'save_box' ), 20 /* Same as add_action call */ );

http://codex.wordpress.org/Function_Reference/remove_action

Make sure you take the $post_id argument in your save_box method too:

function save_box( $post_id ) {
    ...
}
  • Thanks, that's exactly what was causing the problem. Great eye there! – Petr Cibulka Feb 19 '14 at 17:21

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.