How to Debug the 'save_post' Action?

Is it possible to validate PHP code?

I have a Custom Post Type (Film) with Custom Meta Boxes.

Everything is working fine, I can add new Films and details to the Custom Meta Boxes.

My problem is with the Update button. If I create a new film, add info and click Update a get a white screen.

I know the problem is with the function.php and the Custom Post Type but how do I find the mistake?

If I check of the source of the white page it shows 2 empty lines but code has no leading or trailing empty lines.

    <?php
        add_action( 'admin_print_styles-post-new.php', 'film_style', 11 );
        add_action( 'admin_print_styles-post.php', 'film_style', 11 );

        function film_style() {
            global $post_type;
            if( 'films' == $post_type )
                wp_enqueue_style( 'film-style', get_stylesheet_directory_uri() . '/css/filmMetaBox.css');
        }
    ?>

    <?php
        add_action('init', 'film_init');
        function film_init(){
            $film_labels = array(
                'name' => _x('Film', 'post type general name'),
                'singular_name' => _x('Films', 'post type singular name'),
                'all_items' => __('All Films'),
                'add_new' => _x('Add new Film', 'film'),
                'add_new_item' => __('Add new Film'),
                'edit_item' => __('Edit Film'),
                'new_item' => __('New film'),
                'view_item' => __('View film'),
                'search_items' => __('Search in films'),
                'not_found' =>  __('No films found'),
                'not_found_in_trash' => __('No films found in trash'), 
                'parent_item_colon' => ''
            );
            $args = array(
                'labels' => $film_labels,
                'public' => true,
                'publicly_queryable' => true,
                'show_ui' => true,
                'query_var' => true,
                'rewrite' => true,
                'capability_type' => 'post',
                'hierarchical' => false,
                'menu_position' => null,
                'supports' => array('title','editor'),
                'has_archive' => 'films',
                'register_meta_box_cb' => 'cd_meta_box_add'
            );
            register_post_type('films',$args);
        }
    ?>
    <?php
        add_action( 'add_meta_boxes', 'cd_meta_box_add' );
        function cd_meta_box_add(){
          add_meta_box( 'my-meta-box-id', 'Film Credits', 'cd_meta_box_cb', 'films', 'normal', 'high' );
        }

        function cd_meta_box_cb( $post ){
          $values = get_post_custom( $post->ID );

          $title = isset( $values['meta_box_title'] ) ? esc_attr( $values['meta_box_title'][0] ) : '';
          $director = isset( $values['meta_box_director'] ) ? esc_attr( $values['meta_box_director'][0] ) : '';
          $desc = isset( $values['meta_box_desc'] ) ? esc_attr( $values['meta_box_desc'][0] ) : '';

          wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );

          ?>
            <div id="filmMeta">
              <p>
                  <label for="meta_box_title" class="label">Film Title</label>
                  <input type="text" name="meta_box_title" id="meta_box_title" class="textInput" value="<?php echo $title; ?>" />
              </p>
              <p>
                  <label for="meta_box_title" class="label">Director</label>
                  <input type="text" name="meta_box_director" id="meta_box_title" class="textInput" value="<?php echo $director; ?>" />
              </p>
              <p>
                  <label for="meta_box_desc" class="label">Description</label>
                  <textarea name="meta_box_desc" id="meta_box_desc" class="textInput" col="100" row="5"><?php echo $desc; ?></textarea>
              </p>
            </div>
          <?php
        }

        add_action( 'save_post', 'cd_meta_box_save' );
        function cd_meta_box_save( $post_id ){
          if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;// Bail if we're doing an auto save

          // if our nonce isn't there, or we can't verify it, bail
          if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;

          if( !current_user_can( 'edit_post' ) ) return;// if our current user can't edit this post, bail

          $allowed = array( // now we can actually save the data
              'a' => array( // on allow a tags
                  'href' => array() // and those anchords can only have href attribute
              )
          );

          if( isset( $_POST['meta_box_title'] ) )//if data set save it.
              update_post_meta( $post_id, 'meta_box_title', wp_kses( $_POST['meta_box_title'], $allowed ) );
          if( isset( $_POST['meta_box_director'] ) )
              update_post_meta( $post_id, 'meta_box_director', wp_kses( $_POST['meta_box_director'], $allowed ) );
          if( isset( $_POST['meta_box_desc'] ) )
              update_post_meta( $post_id, 'meta_box_desc', wp_kses( $_POST['meta_box_desc'], $allowed ) );
        }
    ?>

Solutions Collecting From Web of "How to Debug the 'save_post' Action?"

Your code works just fine on my end. So, I’d say your problem is elsewhere.

Troubleshooting guide.

You can use standard debugging or FirePHP. I also use the following for cases where FirePHP doesn’t display information, i.e., save_post.

function my_log( $msg, $title = '' )
{
    $error_dir = '/Applications/MAMP/logs/php_error.log';
    $date = date( 'd.m.Y h:i:s' );
    $msg = print_r( $msg, true );
    $log = $title . "  |  " . $msg . "\n";
    error_log( $log, 3, $error_dir );
}

And inside your action callback: my_log( $_POST, 'Contents of $_POST' );.


As far as I know, there’s no such thing as “validate PHP”.
There are editors that’ll show errors while you write: http://www.jetbrains.com/phpstorm/

If you need to var_dump() values in your save_post callback, simply exit; in there:

add_action( 'save_post', 'cd_meta_box_save' );
function cd_meta_box_save( $post_id )
{
    $post = get_post( $post_id );
    // do abort checks
    if (
        wp_is_post_revision( $post );
        OR wp_is_post_autosave( $post );
        OR ! wp_verify_nonce( ... )
        OR ... etc.
    )
        return;

    exit( var_dump( $post, $_POST ) );
}

Method 1:

add_action('save_post', 'something_process1');  function something_process1() {
   if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
   print_r($_POST);
}

Method 2:

create log file (my_logs.txt) in a folder, where you use this code:

add_action('save_post', 'something_process2',11);   function something_process2() {
    print_r($_POST);
    file_put_contents(dirname(__file__).'/my_logs.txt', "\r\n\r\n".ob_get_contents(), FILE_APPEND);
}