wp_set_object_terms()はterm IDとslugの型を分け、appendで置換と追加を選ぶ
公開日: 執筆:佐藤
wp_set_object_terms()を使う前に、対象のobject ID、taxonomy、設定するterm、既存termを残すかを確定します。term IDは整数、slugは文字列として渡してください。第四引数のappendがfalseなら既存の関係を指定内容へ置き換え、trueなら既存の関係を残して追加します。
処理後は返り値も確認します。成功時に返るのはterm IDではなく、設定されたterm_taxonomy_idの配列です。失敗時はWP_Errorが返ります。
object IDとtaxonomyを先に確定する
第一引数のobject_idは、termを結び付ける投稿やlinkなどのIDです。第二引数がterm、第三引数がtaxonomyの識別子になります。WordPress 4.0のwp_set_object_terms()は、object_idを整数へ変換し、taxonomyが登録されていなければWP_Errorを返します。
関数名にpostが含まれていないため、投稿IDだけを扱う関数ではありません。独自post typeへ使う場合も、そのpost typeに結び付けたtaxonomyを第三引数へ指定します。
次は説明用の仮例です。
$post_id = 42;
$term_ids = array( 12, 18 );
$tt_ids = wp_set_object_terms(
$post_id,
$term_ids,
'category',
false
);
if ( is_wp_error( $tt_ids ) ) {
error_log( $tt_ids->get_error_message() );
}
この数字は実在する投稿やtermのIDではありません。実装では、get_post()などで対象objectを確認し、taxonomyがそのobject typeへ結び付いていることも確かめます。wp_set_object_terms()がIDを整数へ変換することと、そのIDが意図した投稿を指すことは別です。
term IDは整数、slugは文字列で渡す
第二引数には、一つのterm ID、一つのslug、またはそれらの配列を渡せます。ただし、PHPの型でIDとslugを区別します。
wp_set_object_terms( $post_id, 12, 'category' );
wp_set_object_terms( $post_id, 'news', 'category' );
上の12は整数のterm ID、newsはslugです。入力欄やrequestから受け取った'12'は数値に見えても文字列なので、slugとして検索されます。そのslugが存在しなければ、文字列12を名前とする新しいtermが作られる可能性があります。
IDとして扱う値は、範囲と存在を検査した後で整数へ変換します。
$term_id = (int) $raw_term_id;
$term = term_exists( $term_id, 'category' );
if ( $term ) {
wp_set_object_terms( $post_id, $term_id, 'category' );
}
整数へ変換すれば正しいtermになるわけではありません。変換後のIDが対象taxonomyに存在することまで確認します。一方、slugで設定する場合は、数値のような文字列をIDだと読み替えず、slugとして扱う意図を明確にします。
appendがfalseなら指定しなかった既存termを外す
第四引数appendの既定値はfalseです。この場合、指定したtermとの関係を作るだけではなく、同じtaxonomyに付いていた既存termのうち、今回指定しなかったものを外します。
たとえば、ある投稿にterm Aとterm Bが付いているとします。term Cだけを指定してappendをfalseにすると、処理後はterm Cだけになります。AとBを残してCを加えるなら、appendをtrueにします。
$tt_ids = wp_set_object_terms(
$post_id,
$term_c_id,
'category',
true
);
置換と追加は、codeの好みで選ぶものではありません。編集画面で選び直した分類を正本として保存するなら置換、既存の分類へ処理結果を足すだけなら追加が候補です。複数の処理が同じtaxonomyを更新する場合は、どの処理が正本を持つかを先に決めます。
返り値の配列はterm taxonomy IDである
成功時の返り値は、関係を設定したterm_taxonomy_idの配列です。term IDの配列として別の処理へ渡さないでください。WordPressでは、一つのtermそのものを表すterm_idと、特定のtaxonomy内でのtermを表すterm_taxonomy_idが分かれています。
$tt_ids = wp_set_object_terms( $post_id, $term_ids, 'category' );
if ( is_wp_error( $tt_ids ) ) {
return $tt_ids;
}
foreach ( $tt_ids as $tt_id ) {
error_log( 'term_taxonomy_id=' . (int) $tt_id );
}
必要なのがterm IDなら、返り値をそのまま使わず、目的に合う取得関数で読み直します。変数名も$term_idsと$tt_idsを分ければ、後の処理で取り違えにくくなります。
権限とnonceは関数を呼ぶ前に確認する
wp_set_object_terms()は、termとの関係を変更する関数です。管理画面の利用者に変更権限があるか、送信が意図した画面から来たかまでは、この関数の中で判断しません。
管理画面や独自formから呼ぶ場合は、対象に応じたcurrent_user_can()の確認と、check_admin_referer()などによるnonceの検査を先に行います。nonceは送信元の意図を確かめる仕組みであり、権限の代わりではありません。権限があってもnonceが不正なら止め、nonceが正しくても権限がなければ止めます。
実装を外部へ任せる場合は、どのroleがどのtaxonomyを変更できるか、置換と追加のどちらを使うか、変更失敗をどこへ記録するかを納品資料へ残します。関数を呼べる状態と、分類を安全に運用できる状態を混同しないでください。
最初の一手は、対象投稿を一件だけ複製し、現在のterm IDを記録することです。整数IDとslugのどちらを使うかを決め、appendをfalseとtrueで別々に試して、返されたterm_taxonomy_idと処理後のtermを確認します。
関連記事

