あるサイトで、コラムの記事の下に、予約・問い合わせの案内の枠を出したときのことです。
この枠は、料金の固定ページや、別の種類の記事の下で、すでに使っていた部品(template-parts のファイル)でした。
コラムの記事でも同じ枠を出したいのですが、見出しとリード文は、コラムに合う文にしたいと考えました。
部品をコピーして 2 つにすると、ボタンや連絡先を直すときに、両方を直すことになります。
そこで、WordPress 5.5 から使える get_template_part() の 3 つ目の引数 $args で、見出しとリード文だけを渡すことにしました。
この記事では、部品の名前を template-parts/contact-box、投稿タイプを my_column などの例の名前にしています。
get_template_part の 3 つの引数
get_template_part() は、テーマの中の部品のファイルを読み込む関数です。
WordPress 5.5 から、3 つ目の引数で、部品に値を渡せるようになりました。
| 引数 | 例 | 役目 |
|---|---|---|
1 つ目 $slug |
'template-parts/contact-box' |
部品のファイル(.php は付けない)。テーマのフォルダから見た場所 |
2 つ目 $name |
null |
部品の別の形の名前。'column' を渡すと、先に contact-box-column.php を探す。null なら contact-box.php だけを読む |
3 つ目 $args |
array( 'title' => '…' ) |
部品に渡す値の配列(5.5 から)。部品の中では $args という名前で使える |
3 つ目の引数だけを使いたいときも、2 つ目は飛ばせません。
別の形の部品は使わないので、2 つ目には null を渡します。
5.5 からは、部品のファイルが見つからなかったときに false を返すようにもなりました。
1. 部品の側:$args を受け取る
<?php
// 予約・問い合わせの案内の枠
// 見出しとリード文は、呼ぶ側から $args で変えられる。渡されなければ既定の文を出す。
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$box_title = $args['title'] ?? 'ご予約・お問い合わせ';
$box_lead = $args['lead'] ?? 'ご相談・ご予約は、お気軽にどうぞ。';
?>
<section class="contact-box">
<h2 class="contact-box__title"><?php echo esc_html( $box_title ); ?></h2>
<p class="contact-box__lead"><?php echo esc_html( $box_lead ); ?></p>
<ul class="contact-box__buttons">
<li><a class="button" href="<?php echo esc_url( home_url( '/contact' ) ); ?>">Web で予約する</a></li>
</ul>
</section>
| 書き方 | 役目 |
|---|---|
$args |
呼ぶ側が 3 つ目の引数で渡した配列。渡さなかったときは空の配列 |
$args['title'] ?? '既定の文' |
title が渡されていればそれを、なければ既定の文を使う。キーがなくても警告は出ない |
esc_html() |
渡された文を、HTML として安全な形にして出す。部品の側で必ず通す |
esc_url() |
リンクの URL を安全な形にして出す |
部品の側で既定の文を持っておくと、今まで引数なしで呼んでいた所は、何も変えなくて済みます。
2. 呼ぶ側:記事の下で見出しを変える
<?php
// 本文の下に、案内の枠を出す
if ( 'my_article' === get_post_type() ) :
// 今までの記事:見出しとリード文は、部品の既定の文のまま
get_template_part( 'template-parts/contact-box' );
endif;
if ( 'my_column' === get_post_type() ) :
// コラムの記事:見出しとリード文だけ変える
get_template_part( 'template-parts/contact-box', null, array(
'title' => 'コラムを読んで気になった方へ',
'lead' => 'コラムの内容についても、お気軽にご相談ください。',
) );
endif;
?>
| 書き方 | 役目 |
|---|---|
get_post_type() |
表示している記事の投稿タイプ |
get_template_part( 'template-parts/contact-box' ) |
引数なし。部品の既定の見出しとリード文が出る(今までどおり) |
null(2 つ目) |
別の形の部品は使わない、という意味 |
array( 'title' => …, 'lead' => … ) |
コラムの記事のときだけ、見出しとリード文を渡す |
ボタンや連絡先は、部品の中に書いてあります。
直すときは、部品のファイル 1 つを直せば、全部の場所に効きます。
3. 固定ページの側:本文の最後に足す
料金の固定ページでは、テンプレートを変えずに、the_content のフィルターで本文の最後に枠を足していました。
<?php
// 固定ページ(料金のページ)の本文の最後に、同じ枠を出す
function my_page_contact_box( $content ) {
if ( ! is_page( 'price' ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}
ob_start();
get_template_part( 'template-parts/contact-box', null, array(
'title' => 'このプランで申し込む',
'lead' => 'メニューや料金のご相談も、お気軽にどうぞ。',
) );
return $content . ob_get_clean();
}
add_filter( 'the_content', 'my_page_contact_box', 20 );
| 書き方 | 役目 |
|---|---|
is_page( 'price' ) |
スラッグが price の固定ページのときだけ |
in_the_loop()・is_main_query() |
メインの本文のときだけ。サイドなどのほかの場所では足さない |
ob_start()・ob_get_clean() |
get_template_part() はそのまま出力するので、いったん文字として受け取る |
$content . ob_get_clean() |
本文の後ろに枠をつなげて返す |
同じ部品を、テンプレートからも、フィルターからも呼べます。
5.5 より前の set_query_var との違い
5.5 より前は、set_query_var() で値を入れてから部品を呼ぶ書き方がよく使われていました。
<?php
// 5.5 より前の書き方(呼ぶ側)
set_query_var( 'box_title', 'コラムを読んで気になった方へ' );
get_template_part( 'template-parts/contact-box' );
// 5.5 より前の書き方(部品の側)
$box_title = get_query_var( 'box_title' );
if ( '' === $box_title ) {
$box_title = 'ご予約・お問い合わせ';
}
$args(5.5 から) |
set_query_var()(5.5 より前) |
|
|---|---|---|
| 渡し方 | get_template_part() の 3 つ目の引数 |
呼ぶ前に set_query_var() で入れる |
| 部品の中での受け取り方 | $args['title'] |
get_query_var( 'box_title' )(同じ名前の変数 $box_title としても見える) |
| 値が残る範囲 | その 1 回の呼び出しの中だけ | メインのクエリに残り、あとで呼ぶ部品にも見える |
| 名前のぶつかり | 気にしなくてよい | クエリの変数(page・name など)と同じ名前にすると、ほかの処理に影響することがある |
| 使える WordPress | 5.5 から | 古いバージョンでも使える |
今の WordPress なら、渡した値がその場だけで終わる $args のほうが、ほかへの影響を考えずに済みます。
?? と ! empty() の違い
既定の文に切り替える書き方は、2 つあります。
空の文字('')を渡したときに、結果が変わります。
| 渡したもの | $args['title'] ?? '既定の文' |
! empty( $args['title'] ) ? $args['title'] : '既定の文' |
|---|---|---|
| 渡さない | 既定の文 | 既定の文 |
'新しい見出し' |
新しい見出し | 新しい見出し |
''(空) |
空のまま(見出しが空になる) | 既定の文 |
このサイトの部品は、空のときも既定の文になる ! empty() の形で書いています。
<?php // 空の文字が渡されたときも、既定の文にしたいとき $box_title = ! empty( $args['title'] ) ? $args['title'] : 'ご予約・お問い合わせ';
確かめた結果
このサイトの作業環境(本番から複製したもの・WordPress 7.1.3・PHP 8.3)で確かめました。
ページで見た
それぞれのページを、URL に ?nc=(乱数)を付けて、キャッシュを通さずに開きました。
| ページ | 結果 |
|---|---|
| コラムの記事 | 200。本文の下・カテゴリーの上に枠が 1 つ出た。見出しは「コラムを読んで気になった方へ」、リード文もコラム用の文に変わった |
| 別の種類の記事(引数なしで呼んでいる所) | 200。枠が 1 つ出た。見出しとリード文は、部品の既定の文のまま |
| 料金の固定ページ(フィルターで足している所) | 200。枠が 1 つ出た。見出しとリード文は、そのページ用の文のまま(今までどおり) |
どのページにも、PHP の Fatal error や Warning は出ていませんでした。
値の渡り方
検証用スクリプトで作業環境の WordPress を読み込み、小さな部品のファイルを、get_template_part() が中で使う load_template() で読み込みました。
| 試したこと | 結果 |
|---|---|
| 引数なし | $args は空の配列。既定の文が出た |
array( 'title' => '新しい見出し' ) |
新しい見出しが出た |
array( 'title' => '' ) |
?? は空、! empty() は既定の文 |
$args で渡したあと、引数なしでもう一度呼ぶ |
既定の文に戻った(値は残らない) |
set_query_var() で入れてから呼ぶ |
部品の中で、同じ名前の変数として見えた |
| そのあと、何もせずにもう一度呼ぶ | set_query_var() の値が、まだ見えた(残っている) |
ない部品を get_template_part() で呼ぶ |
false が返った |
検証用スクリプトは、DB には何も書いていません。
気をつけること
$argsで渡した文は、部品の側でesc_html()などを通して出します。呼ぶ側を信じて、そのまま出さないようにします- 見出しに HTML(太字など)を入れたいときは、
esc_html()では文字として出てしまいます。そのときはwp_kses_post()などに変えます(このサイトでは文だけなので、試していません) - 部品の中で、
id属性を決まった値で書いていると、同じページで 2 回使ったときにidが重なります。このサイトでは 1 ページに 1 つだけなので、そのままにしています - 5.5 より前の WordPress では、3 つ目の引数は使えません(渡しても部品には届きません)
- 子テーマを使っているときは、
get_template_part()は子テーマの部品を先に探します
まとめ
- WordPress 5.5 から、
get_template_part( $slug, $name, $args )の 3 つ目の引数で、部品に値を渡せる - 別の形の部品を使わないときは、2 つ目に
nullを渡す - 部品の側で
$args['title'] ?? '既定の文'のように既定の文を持てば、今までの呼び出しは変えなくて済む。空のときも既定にしたいなら! empty() - 渡した値は、部品の側で
esc_html()を通して出す set_query_var()と違い、$argsの値はその呼び出しの中だけで終わる


