カスタムフィールドで内容を構成する記事では、投稿タイトルを手入力する必要がない(むしろ不要な)ことがあります。とはいえ、WordPressの管理上はタイトルがある方が扱いやすいものです。
結論から言うと、save_postフックで、カスタムフィールドの値やタクソノミーのタームからタイトルを組み立て、wp_update_post()で自動生成することができます。ただし、そのままだと無限ループに陥るため、その回避策もあわせて解説します。
functions.phpに、次のコードを追記します。カスタム投稿タイプmenuで、タクソノミーmenucatのターム名と、カスタムフィールドinfo1〜3を組み合わせてタイトルを生成する例です。
function rename_post_title($post_id)
{
global $post;
$menucat_term = wp_get_object_terms($post->ID, 'menucat'); // タクソノミーを使う場合はここで指定
$menucat_term_name = $menucat_term[0]->name; // ターム名
if ($post->post_type == 'menu') { // 投稿タイプの確認
// タイトルになる文字列を生成
$title = $menucat_term_name . ' / ' . get_post_meta($post_id, 'info1', true) . ' / ' . get_post_meta($post_id, 'info2', true) . ' / ' . get_post_meta($post_id, 'info3', true);
// 現在のタイトルと異なる場合のみ更新
if (get_the_title($post_id) !== $title) {
// 自分をフック解除して無限ループを防ぐ
remove_action('save_post', 'rename_post_title');
// 生成したタイトルに書き換え
wp_update_post(['ID' => $post_id, 'post_title' => $title]);
// 自分を改めてフックする
add_action('save_post', 'rename_post_title');
}
}
}
add_action('save_post', 'rename_post_title');
タクソノミーを使わず、カスタムフィールドの値だけでタイトルを作りたい場合は、ターム名の部分を外して$titleを組み立ててください。投稿タイプ名(menu)やフィールド名(info1など)は、実際の設定に合わせて置き換えます。
コードの中では、wp_get_object_terms()で投稿に紐づくタームを取得し、get_post_meta()でカスタムフィールドの値を取り出しています。これらを/でつなげて、1つのタイトル文字列にしています。
なお実運用では、自動保存やリビジョンの保存でもsave_postが発火します。必要に応じて、wp_is_post_revision()やDOING_AUTOSAVEのチェックを加えておくと、意図しないタイミングでの実行を防げて安全です。
このコードでいちばん重要なのが、無限ループの回避です。参考にした記事の通りに実装したところ、記事を更新すると読み込みが止まらず、いつまでも更新が終わらない状態になってしまいました。
原因は、save_postフックの中でwp_update_post()を呼んでいることにあります。wp_update_post()は投稿を保存する関数なので、これが再びsave_postを発火させ、またrename_post_title()が呼ばれ……と、処理が延々と繰り返されてしまうのです。
これを防ぐには、wp_update_post()を呼ぶ前に自分自身のフックを一度解除(remove_action)し、処理が終わったら改めてフックし直す(add_action)のが定石です。こうすることで、タイトル更新のための保存ではrename_post_title()が呼ばれなくなり、ループを断ち切れます。あわせて「現在のタイトルと異なる場合のみ更新する」条件も入れておくと、無駄な更新を避けられます。
save_postフックで、カスタムフィールドやタームからタイトルを自動生成できるwp_update_post()を使うとsave_postが再発火し、無限ループになるremove_action/add_actionし、ループを防ぐタイトルを自動生成できると、入力の手間が減り、命名のばらつきもなくなります。カスタムフィールド主体の投稿を扱うときに、覚えておくと便利なテクニックです。