wp_insert_post()は投稿データを検証し、返された投稿IDまたはWP_Errorを確認する
公開日: 執筆:佐藤
wp_insert_post()で投稿を追加するときは、関数を呼ぶ前に入力値と公開状態を決めます。第二引数へtrueを渡し、返り値がWP_Errorなら処理を止め、投稿IDが返ったときだけ次の処理へ進みます。
関数が投稿データをデータベース用に整えることと、外部入力を信頼できるか、実行者に投稿する権限があるかを判断することは別です。権限、nonce、入力の用途は、呼出側で確認してください。
投稿データでは使う項目を明示する
wp_insert_post( $postarr, $wp_error )の第一引数には、投稿データの配列を渡します。WordPress 3.9.1の公式Coreでは、post_statusの初期値はdraft、post_typeの初期値はpostです。post_authorはログイン中の利用者になります。
初期値がある項目も、処理の目的に必要なら明示します。自動登録のコードで公開状態を省略すると、読む人が下書きを意図したのか、省略に気付かなかったのかを判断できません。
最初は次の項目へ絞ります。
| 項目 | 呼出前に決めること |
|---|---|
post_title |
空欄を許すか、どの文字列を題名にするか |
post_content |
許可するHTMLと不要な文字列をどう扱うか |
post_status |
draftとして確認を待つか、別の状態にするか |
post_type |
通常の投稿か、登録済みの別の投稿タイプか |
カテゴリー、タグ、日付、投稿者まで同時に自動設定する前に、投稿本体が正しく追加されることを確かめます。
外部入力はwp_insert_post()の前で検証する
フォームや外部ファイルから得た値を、そのまま$postarrへ入れてはいけません。呼出側で、処理を実行できる利用者か、正しい画面から送られた要求か、値が期待する形式かを確認します。
管理画面のフォームなら、少なくとも権限とnonceを確認します。そのあとで題名を一行の文字列へ整え、本文に許すHTMLを決めます。
次は、検証済みの題名と本文から下書きを追加する説明用の仮例です。フォーム受信と権限確認は、この関数を呼ぶ前に完了しているものとします。
function satolab_insert_note( $raw_title, $raw_content ) {
if ( ! is_string( $raw_title ) || ! is_string( $raw_content ) ) {
return new WP_Error( 'invalid_note_data', '投稿データの形式が正しくありません。' );
}
$post_title = trim( wp_strip_all_tags( $raw_title ) );
$post_content = wp_kses_post( $raw_content );
if ( '' === $post_title && '' === trim( $post_content ) ) {
return new WP_Error( 'empty_note', '題名または本文を入力してください。' );
}
$post_data = array(
'post_title' => $post_title,
'post_content' => $post_content,
'post_status' => 'draft',
'post_type' => 'post'
);
$post_id = wp_insert_post( wp_slash( $post_data ), true );
if ( is_wp_error( $post_id ) ) {
return $post_id;
}
return $post_id;
}
題名からすべてのHTMLを除き、本文では投稿本文に許されるHTMLを残しています。wp_insert_post()がslashed dataを受け取る前提に合わせ、整えた配列をwp_slash()へ渡します。どのHTMLを許すかは入力元と用途で変わるため、この処理をすべての投稿登録へ機械的に使うものではありません。
第二引数をtrueにして失敗理由を受け取る
wp_insert_post()は、成功すると投稿IDを返します。失敗時は、第二引数がfalseなら0、trueならWP_Errorを返します。
WordPress 3.9.1のCoreでは、題名、本文、抜粋がすべて空で、投稿タイプがそれらの機能を備える場合、空の投稿として処理を中止します。無効な投稿IDによる更新、不正な日付、データベースへの追加失敗も、第二引数がtrueならWP_Errorとして確認できます。
失敗時に0だけを受け取るより、WP_Errorのcodeとmessageを記録した方が原因を分けられます。ただし、利用者へデータベースの詳細をそのまま表示してはいけません。画面には操作に必要な説明を出し、詳しい記録は管理者が確認できる場所へ残します。
投稿IDを確認してから次の処理へ進む
投稿IDは、投稿が追加されたことを示す返り値です。返り値を確認せず、直後にカスタムフィールドや分類を追加すると、失敗した投稿へ続く処理まで動かすことになります。
呼出側では次のように分けます。
$post_id = satolab_insert_note( $title, $content );
if ( is_wp_error( $post_id ) ) {
error_log( $post_id->get_error_code() . ': ' . $post_id->get_error_message() );
return;
}
update_post_meta( $post_id, 'source_name', 'manual-entry' );
manual-entryは説明用の値です。実在する登録経路や実績を示すものではありません。
追加後に必要な処理が複数あるなら、どの段階まで成功したかを記録します。投稿だけが追加され、分類やカスタムフィールドの設定が失敗する可能性は残ります。投稿IDを得たことと、一連の作業がすべて完了したことを同じにしないでください。
権限とnonceは呼出側の責任として残す
wp_insert_post()の内部には、特定の状態や投稿者を扱うための処理があります。しかし、この関数を呼べた要求が正規の操作か、実行者が独自機能を使ってよいかを、用途に合わせてすべて確認する関数ではありません。
管理画面から実行するなら、画面を表示する権限、処理を実行する権限、nonce、入力値を呼出側で確認します。定期処理や取込処理なら、入力ファイルの所有者、再実行したときの重複、失敗記録、停止方法も決めます。
作業を外部の制作者へ委託しても、どの入力から何の投稿を作り、誰が下書きを確認し、どの記録で失敗を追うかは、サイト所有者が把握できるようにします。
最初の一手は、post_title、post_content、post_status、post_typeだけで一件の下書きを追加することです。第二引数をtrueにし、投稿IDとWP_Errorの両方を意図的に確認してから、分類やカスタムフィールドを加えてください。
関連記事

