web-dev-qa-db-ja.com

投稿IDを渡し、異なる投稿タイプのカスタムメタボックスを保存するときにsave_post関数が競合しています

保存後関数は、それらをsave_postアクションフックに追加するときに競合します。

2つの異なるカスタム投稿タイプ(2つの異なる投稿タイプごとに1つ)のカスタムメタボックス。

私はメタボックスのうちの1つのコードを含めているだけです。もう一方は非常によく似ていて、それぞれが別々にうまく機能しますが、一緒には機能しません。

'register_metabox_cb'コールバック関数

function c3m_video_meta() {
    add_meta_box('_c3m_video_embed', __('Enter Video Embed Code In the Box Below') , 'c3m_video_embed', 'video', 'normal', 'low');
    }

投稿編集画面にメタボックスを追加する:

function c3m_video_embed($post) {
    global $post;
    wp_nonce_field(__FILE__,'video_nonce');
    $embed-code = get_post_meta($post->ID, '_embed-code', true);
    echo '<input type="text" name="_embed-code" value=""' . $embed-code . '" class="widefat" />' ; 
    }

保存機能:

  function c3m_save_video_meta( $post_id , $post ) { 

            if ( !wp_verify_nonce( $_POST [ 'video_nonce' ], __FILE__ ) ) { return $post ->ID; 
            }
            if ( !current_user_can( 'edit_post' , $post ->ID )) return $post ->ID; 
            $c3m_video_embed-code [ '_embed-code' ] = $_POST [ '_embed-code' ]; 
                        foreach ( $c3m_video_embed-code as $key => $value ) { 
                        if ( $post ->post_type == 'revision' ) return ; 

                        $value = implode( ',' , ( array ) $value );
                        if (get_post_meta( $post ->ID, $key , FALSE)) { 
                        update_post_meta( $post ->ID, $key , $value ); } else { 
                        add_post_meta( $post ->ID, $key , $value ); } if (! $value ) delete_post_meta( $post ->ID, $key ); 
                        }
}

アクションフック:

add_action( 'admin_menu' , 'c3m_video_meta' );

add_action( 'save_post' , 'c3m_save_video_meta' , 1, 2);

これは問題がなく手間のかかる作業ですが、別の投稿タイプに別のメタボックスを追加し、投稿の保存時に同様の機能(異なる機能名、ナンス名、およびキー)を使用すると、次のエラーが表示されます。

Notice:未定義のインデックス:/Applications/MAMP/htdocs/wordpress/wp-content/plugins/ieew-custom-functions/ieew-custom-functions.phpの181行目の_embed-code

Warning:ヘッダ情報を変更することはできません - /Applications /の/Applications/MAMP/htdocs/wordpress/wp-content/plugins/ieew-custom-functions /ieew-custom-functions.php:181から出力されたヘッダ) 897行目のMAMP/htdocs/wordpress/wp-includes/pluggable.php

未定義の_embed-codeは、_embed-code変数を含まない投稿を保存するときです。

保存しようとしている投稿タイプに応じてエラーメッセージが逆になるので、両方の(2つの)保存機能がsave_postアクションに追加されていると信じるようになります。通常の投稿を保存するときにも追加されます。通常の投稿を保存するときに、保存機能を1つだけ使用している場合はエラーはありません。

この質問が「コードを修正する」の質問ではなく、カスタムメタボックスを追加してさまざまなナンスを使用する方法とその理由メソッドもちろん、More Fieldsプラグインを使用することもできますが、カスタムコンテンツタイプを使用して投稿編集画面をカスタマイズするための最善の方法を学ぶことをお勧めします。

私はこれと同じコードと方法を使用して、単一のカスタム投稿タイプに複数のメタボックスを追加しましたが、これは常にうまく機能しています。

1
Chris_O

もう少し調べたところ、次のことがわかりました。

  • add_meta_box関数をadmin_menuにフックする代わりに、それはadd_meta_boxesにフックされるべきです
  • Foreachループの代わりに、save関数にupdate_post_meta関数を使用してください。
  • wp_nonce_fieldを使用する代わりに、esc_attrおよびstrip_tagsを使用してデータをサニタイズすることができます。
  • 投稿IDをメタボックスの保存機能に渡すために、追加の$ post変数を含める必要はありません。
  • あなたは保存機能に投稿タイプの条件付き状態を追加しなければなりません
  • Save関数でglobal $postを呼び出す必要があります

両方のメタボックスを追加するための新しくてはるかに単純なコード:

add_action( 'add_meta_boxes', 'c3m_sponsor_meta' );

function c3m_sponsor_meta() {
    add_meta_box( 'c3m_sponsor_url', 'Sponsor URL Metabox', 'c3m_sponsor_url', 'sponsor', 'side', 'high' );
}

function c3m_sponsor_url( $post ) {
    $sponsor_url = get_post_meta( $post->ID, '_sponsor_url', true);
    echo 'Please enter the sponsors website link below';
    ?>
        <input type="text" name="sponsor_url" value="<?php echo esc_attr( $sponsor_url ); ?>" />
    <?php
}

add_action( 'save_post', 'c3m_save_sponsor_meta' );

function c3m_save_sponsor_meta( $post_id ) {
    global $post;
    if( $post->post_type == "sponsor" ) {
        if (isset( $_POST ) ) {
            update_post_meta( $post_ID, '_sponsor_url', strip_tags( $_POST['sponsor_url'] ) );
        }
    }
}

add_action( 'add_meta_boxes', 'c3m_video_meta' );        

function c3m_video_meta() {
    add_meta_box( 'c3m_video_embed_code', 'Video Embed Code Meta Box', 'c3m_video_embed_code', 'video', 'normal', 'high' );
}

function c3m_video_embed_code( $post ) {
    $embed_code = get_post_meta( $post->ID, '_embed_code', true);
    echo 'Please enter the video embed code below';
    ?>
        <input type="text" name="embed_code" value="<?php echo esc_attr( $embed_code ); ?>" />
    <?php
}

add_action( 'save_post', 'c3m_save_video_meta' );

function c3m_save_video_meta( $post_id ) {
    global $post;
    if( $post->post_type == "video" ) {
        if (isset( $_POST ) ) {
            update_post_meta( $post_ID, '_embed_code', strip_tags( $_POST['embed_code'] ) );
        }
    }
}
3
Chris_O

Wp_nonce_fieldを使う代わりに、esc_attrとstrip_tagsを使ってデータをサニタイズすることができます。

私は一回だけを使う代わりにデータをエスケープする論理に従わないのですか? wordpress.orgで与えられた例は意図を確かめるために一回だけを使います、そしてまたそれを挿入する前にデータをエスケープします。これら二つのことはどう関係しているのでしょうか。

1
Milo

グローバルな$ postをする必要はないはずです。間違いなくそれを関数に渡すことができます。

私は2つの異なるsave_postアクションを持っていました。1つは同じ投稿タイプのクイック編集用で、もう1つはメタボックス用です。 2つの項目が同じデータをカバーしていたので、私は同じナンス生成名を使用しました。

いずれにせよ、私はあなたのsave_post関数を1 ... ORに結合してnonceをチェックする前にポストタイプをチェックすることを検討するでしょう。

add_action( 'save_post' , 'c3m_save_meta' , 20, 2); //moved priority to later. you had priority 1 so is possible that WP actions were happening after your code

function c3m_save_meta( $post_id , $post ) {   

   // 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 $post_id;

   //don't save if only a revision
   if ( $post->post_type == 'revision' ) return $post_id;   

   // Check permissions
   if ( 'page' == $post->post_type ) {
    if ( !current_user_can( 'edit_page', $post_id ) ) return $post_id;
   } else {
    if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id;
   }      

  //save video post meta
  if( $post->post_type == "video" && wp_verify_nonce( $_POST [ 'video_nonce' ], __FILE__ )) {
     if (isset( $_POST['_embed_code'] ) ) {
        update_post_meta( $post_ID, '_embed_code', esc_attr( $_POST['embed_code'] ) );
     }
  }

  //save sample bacon post meta
   if( $post->post_type == "bacon" && wp_verify_nonce( $_POST [ 'bacon_nonce' ], __FILE__ )) {
      if (isset( $_POST['_bacon_code'] ) ) {
        update_post_meta( $post_ID, '_bacon_code', esc_attr( $_POST['bacon_code'] ) );
      }
   }
}

または、両方のメタボックスに同じ一回だけの名前を使用することもできます。このセキュリティについてはコメントできませんが、WPがクイック編集モードでも通常の編集モードでも_wpnonceと同じことをしているように見えるので、私には問題ないようです。 WPには、メタボックスごとに個別のノンスがあるとは限りません。

function c3m_save_meta( $post_id , $post ) {   
       if(!wp_verify_nonce( $_POST [ 'c3m_nonce' ], __FILE__ )) return $post_id; //change both nonces to name=c3m_nonce

       // 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 $post_id;  

       //don't save if only a revision
       if ( $post->post_type == 'revision' ) return $post_id; 

       // Check permissions
       if ( 'page' == $post->post_type ) {
        if ( !current_user_can( 'edit_page', $post_id ) ) return $post_id;
       } else {
        if ( !current_user_can( 'edit_post', $post_id ) ) return $post_id;
       }      

      //save video post meta
      if( $post->post_type == "video") {
         if (isset( $_POST['_embed_code'] ) ) {
            update_post_meta( $post_ID, '_embed_code', esc_attr( $_POST['embed_code'] ) );
         }
      }

      //save sample bacon post meta
       if( $post->post_type == "bacon" && wp_verify_nonce( $_POST [ 'bacon_nonce' ], __FILE__ )) {
          if (isset( $_POST['_bacon_code'] ) ) {
            update_post_meta( $post_ID, '_bacon_code', esc_attr( $_POST['bacon_code'] ) );
          }
       }
    }
1
helgatheviking