同じ部品の見出しを場所ごとに変える:get_template_part の 3 つ目の引数 $args の使い方

広告WordPress・PHP を学べる本

Amazonのアソシエイトとして、WordPress functions.phpは適格販売により収入を得ています。

あるサイトで、コラムの記事の下に、予約・問い合わせの案内の枠を出したときのことです。

この枠は、料金の固定ページや、別の種類の記事の下で、すでに使っていた部品(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 を受け取る

/wp-content/themes/(テーマのフォルダ)/template-parts/contact-box.php
<?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. 呼ぶ側:記事の下で見出しを変える

single.php(本文の下)
<?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 のフィルターで本文の最後に枠を足していました。

functions.php(またはテーマから読むファイル)
<?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() で値を入れてから部品を呼ぶ書き方がよく使われていました。

5.5 より前の書き方(比べるため)
<?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 の値はその呼び出しの中だけで終わる

参考

関連機能

  1. WordPress作業にてよく使うChrome拡張機能 作業の効率UP! テーマ、プラグインの調査に大活躍な便利機能

  2. WordPress タグクラウドの最大表示件数を変更する

  3. WordPress 記事の新規作成時に公開状態の初期値を非公開にする

サイドバー

よく使うカスタマイズ

最近の記事

Profile

PAGE TOP