web-dev-qa-db-ja.com

カスタムフィールドを保存するときに検証とエラー処理を追加しますか?

投稿タイプのカスタムフィールドを定義する関数があります。フィールドが "subhead"だとしましょう。

投稿が保存されたら、入力を検証し、必要に応じて投稿編集画面にエラーメッセージを表示します。何かのようなもの:

// Handle post updating
function wpse_update_post_custom_values($post_id, $post) {

    // Do some checking...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors->add('oops', 'There was an error.');

    }

    return $errors;

} 
add_action('save_post','wpse_update_post_custom_values',1,2);

これをsave_postアクションにフックしようとしていますが、エラーの処理方法がわかりません。関数にエラーオブジェクトが渡されているようには見えません。自分でWP_Error objを作成してそれを返す場合、投稿編集ページでエラーが発生したとしてもそれは尊重されません。

現在、カスタムメタボックス内にページ上のエラーメッセージが表示されていますが、これは理想的とは言えません。通常は、WPのように大きくて赤いエラーが発生します。を表示します。

何か案は?

更新:

@Denisの答えに基づいて、私はいくつかのことを試しました。グローバルとしてエラーを保存することはうまくいきませんでした、なぜならWordpressはあなたがそれを表示することができる前にグローバルを殺すsave_postプロセスの間にリダイレクトをするからです。

私はそれらをメタフィールドに格納することになりました。これに関する問題は、あなたがそれらをクリアする必要があるか、あるいはあなたが別のページに移動したときにそれらが消えないということです、それで私はただエラーをクリアするadmin_footerに付けられた別の関数を追加しなければなりません。

それほど一般的なもの(投稿の更新)のエラー処理がこれほど不器用になるとは思わなかったでしょう。明らかな何かが足りないのでしょうか、それともこれが最善のアプローチですか?

// Handle post updating
function wpse_5102_update_post_custom_values($post_id, $post) {

    // To keep the errors in
    $errors = false;

    // Do some validation...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors .= 'whoops...there was an error.';

    }

    update_option('my_admin_errors', $errors);

    return;

} 
add_action('save_post','wpse_5102_update_post_custom_values',1,2);


// Display any errors
function wpse_5102_admin_notice_handler() {

    $errors = get_option('my_admin_errors');

    if($errors) {

        echo '<div class="error"><p>' . $errors . '</p></div>';

    }   

}
add_action( 'admin_notices', 'wpse_5102_admin_notice_handler' );


// Clear any errors
function wpse_5102__clear_errors() {

    update_option('my_admin_errors', false);

}
add_action( 'admin_footer', 'wpse_5102_clear_errors' );
29
MathSmath

エラーをクラスに、またはグローバルに、おそらく一時的またはメタに格納し、POST要求の管理通知に表示します。 WPにはフラッシュメッセージハンドラはありません。

7

2人のユーザーが同時に編集するときに奇妙な効果が生じることはないので、セッションを使用することをお勧めします。だからこれは私がしていることです:

セッションはwordpressによって開始されません。それであなたは セッションを開始する必要があります あなたのプラグイン、functions.phpあるいはwp-config.phpで:

if (!session_id())
  session_start();

投稿を保存するときに、エラーと通知をセッションに追加します。

function my_save_post($post_id, $post) {
   if($something_went_wrong) {
     //Append error notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="error"><p>This or that went wrong</p></div>';
     return false; //might stop processing here
   }
   if($somthing_to_notice) {  //i.e. successful saving
     //Append notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="updated"><p>Post updated</p></div>';
   }

   return true;
} 
add_action('save_post','my_save_post');

通知とエラーを表示してから、セッション内のメッセージを消去します。

function my_admin_notices(){
  if(!empty($_SESSION['my_admin_notices'])) print  $_SESSION['my_admin_notices'];
  unset ($_SESSION['my_admin_notices']);
}
add_action( 'admin_notices', 'my_admin_notices' );
6
davidn

pospi s 提案 を使用して トランジェント に基づいて、次のように思いつきました。唯一の問題は、メッセージを他のメッセージがあるh2の下に置くためのフックがないことです。そこで私はjQueryをハックしてそこに到達する必要がありました。

まず、save_post(または類似の)ハンドラの実行中にエラーメッセージを保存します。私はそれに60秒という短い寿命を与えるので、リダイレクトが起こるのにちょうど十分な長さがあります。

if($has_error)
{
  set_transient( "acme_plugin_error_msg_$post_id", $error_msg, 60 );
}

次に、次のページの読み込み時にそのエラーメッセージを取得して表示します。 2回表示されないように、私もそれを削除します。

add_action('admin_notices', 'acme_plugin_show_messages');

function acme_plugin_show_messages()
{
  global $post;
  if ( false !== ( $msg = get_transient( "acme_plugin_error_msg_{$post->ID}" ) ) && $msg) {
    delete_transient( "acme_plugin_error_msg_{$post->ID}" );
    echo "<div id=\"acme-plugin-message\" class=\"error below-h2\"><p>$msg</p></div>";
  }
}

プライマリページのコンテンツが生成される前にadmin_noticesが起動されるので、他の編集後メッセージがある場所には通知されないので、このjQueryを使用して移動する必要がありました。

jQuery('h2').after(jQuery('#acme-plugin-message'));

投稿IDは一時的な名前の一部なので、複数のユーザーが同じ投稿を同時に編集している場合を除き、これはほとんどのマルチユーザー環境で機能します。

5
Joshua Coady

save_postが実行されるとき、それはすでにデータベースに投稿を保存しています。

WordPressのコアコード、特にwp-includes/post.phpupdate_post()関数に目を向けると、要求がデータベースに保存される前にそれを傍受するための組み込みの方法はありません。

ただし、投稿が保存されないようにするためにpre_post_updateをフックしてheader()get_post_edit_link()を使用することができます。

<?php

/**
*   Performs validation before saving/inserting custom post type
*/
function custom_post_site_save($post_id, $post_data) {
    // If this is just a revision, don't do anything.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'my_custom_post_type') {
        // Deny post titles with less than 5 characters
        if (strlen($post_data['post_title'] < 5)) {
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

何が問題なのかをユーザーに通知するには、次の項目をチェックしてください。 https://Gist.github.com/Luc45/09f2f9d0c0e574c0285051b288a0f935

2

Javascriptを使って自分の分野を検証してみませんか。私はこれがこれのための最善のアプローチだろうと思います。

1
Horttcore

上記のスクリプトを使用しようとしたところ、私は奇妙な問題に遭遇しました。更新後に、2つのメッセージが編集画面に表示されます。 1つは前回の保存からのコンテンツの状態を示し、もう1つは現在の保存からのコンテンツの状態を表示しています。たとえば、投稿を正しく保存してからエラーを発生させた場合、最初のエラーは「エラー」、2番目のエラーは「OK」です。ただし、それらは同時に生成されます。スクリプトを変更してメッセージを1つだけ追加した場合(例: "error")、 "error"で更新を1回開始し、その後 "ok"で別の更新を続けます(2回目に表示されます)。それを取り除くためにもう一度 "ok"で保存しなければなりません。何が悪いのか本当にわかりません。3つの異なるローカルサーバーでテストしましたが、それぞれ同じ問題があります。誰かアイデアや提案があれば、助けてください!

1
jlub

投稿編集画面のフラッシュエラー処理を追加し、必須フィールドに入力するまで投稿が公開されないようにするプラグインを作成しました。

https://github.com/interconnectit/required-fields

任意の投稿フィールドを必須にすることができますが、カスタマイズ可能なエラーメッセージと検証機能を使用して必要なカスタムフィールドを作成するために提供されているAPIを使用することもできます。デフォルトでは、フィールドが空かどうかを調べます。

0
sanchothefat