save_post にフックした関数内で setup_postdata を使おうとしてちょっとつまづいた件

テンプレートで出力される内容を $post->post_content に入れる

ショップというカスタム投稿タイプを作って、このショップの投稿では店名や住所などをカスタムフィールドで入力して、それら情報のみをページに出力。このとき本文はそもそも入力しないというケース。

このままでは $post->post_content が空っぽなので、たとえばカスタムフィールドで入力した住所などで検索したときにヒットしない。

カスタムフィールドを検索対象にするという手もあるけど、データベースに負荷かかるし、 $post->post_content が空っぽなのはやはりちょっとイヤなので、記事を保存するときに出力されるページのコンテンツ部分を $post->post_content にぶっこむことにする。

こういう場合はアクションフック save_post を使えばいいので、最初は次のようにした。

function save_shop( $post_id, $post, $update ) {

	if ( $post_obj->post_type == 'shop' ) {

		ob_start();

		setup_postdata( $post );

		get_template_part( 'templates/content', 'shop' );

		$shop_content = ob_get_contents();

		wp_reset_postdata();

		ob_end_clean();


		$args = array(
			'ID' => $post_id,
			'post_content' => $shop_content,
		);

		remove_action( 'save_post', 'save_shop' );

		wp_update_post( $args );

		add_action( 'save_post', 'save_shop', 10, 3 );

	}

}


add_action( 'save_post', 'save_shop', 10, 3 );

get_template_part( ‘templates/content’, ‘shop’ ) で出力される内容を ob_get_content() で取得して $shop_content に代入。その後、wp_update_post() で投稿データを更新する。

ちなみにこのとき、remove_action( ‘save_post’, ‘save_shop’ ) としているのは wp_update_post() でフックした関数が呼び出されてしまい無限ループに陥いるのを避けるため。

参考) プラグイン API/アクションフック一覧/save post

うまく行ったかに思えたけど、一括操作で更新するとうまく行かない…

これで投稿を更新してみたら、うまく行った。ところが投稿一覧で投稿を選択して、一括操作の編集でまとめて更新してみるとうまく行かない。

テンプレートの内容は取得できているようだけど、肝心のカスタムフィールドの値が取得できていない。。どうも setup_postdata( $post ) がうまく働いていないよう。うーんなんでだろうと調べてみたら、公式リファレンスには

$post グローバル変数へのリファレンスを指定しなければなりません。そうしないと the_title() などの関数が正しく動作しません。

出典: 関数リファレンス/setup postdata

要は setup_postdata( $post ) の $post はグローバル変数の $post にしなければいけないということのようだ。

上記のコードの $post はフックした関数 save_shop が受け取った引数なわけだ。

ってことで、 以下のように save_shop( $post_id, $post_obj, $update ) と修正して、この関数内でグローバル変数 $post を呼び出して、$post = $post_obj と割り当ててやればうまく行った。

function save_shop( $post_id, $post_obj, $update ) {

	if ( $post_obj->post_type == 'shop' ) {
                global $post; 
                $post = $post_obj; 

		ob_start();
                
		setup_postdata( $post );

		get_template_part( 'templates/content', 'shop' );

		$shop_content = ob_get_contents();

		wp_reset_postdata();

		ob_end_clean();


		$args = array(
			'ID' => $post_id,
			'post_content' => $shop_content,
		);

		remove_action( 'save_post', 'save_shop' );

		wp_update_post( $args );

		add_action( 'save_post', 'save_shop', 10, 3 );


	}

}


add_action( 'save_post', 'save_shop', 10, 3 );

setup_postdata( $post ) の $post はグローバル変数、ってのは頭のなかにはあったはずだけど、つい忘れていたということで以上まとめてみました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です