この記事は「絞り込み検索をプラグインで実装してみよう」の続きです。
カスタマイズする内容は次の2つです。
- ショップ検索ページのヘッダータイトルをショップ検索に変更する
- 各フロアの検索結果を表示する際に、フロアマップの画像も表示する
Lightningで使用されている検索ページのテンプレートファイルを直接編集せずに、フックを使ってカスタマイズします。
それでは、検索ページのテンプレートファイル「index.php」を読み解いていきましょう。
フックとは
まず、フックについて理解しましょう。フックには2つの種類があります。
アクションフック(Action Hook)
アクションフックは、特定のタイミングで追加の処理を実行するための仕組みです。
do_action( 'フック名' );
は、独自のコードを挿入できる場所を提供するadd_action( 'フック名', 'コールバック関数' );
を使って、アクションフックにコールバック関数を追加する
次のような流れで処理されます。
do_action( 'hook_name', $arg1, $arg2, ... );
が実行される- そのフックに登録されたコールバック関数が
$arg1, $arg2, ...
を引数として受け取る - 受け取った引数を使って処理を実行する
- すべての登録関数の処理が完了すると、
do_action()
の呼び出し元の処理が続行される
フィルターフック(Filter Hook)
フィルターフックは、特定のタイミングで値を変更するための仕組みです。
apply_filters( 'フィルター名', 'フィルターする値' );
は、コンテンツやデータを変更できる場所を提供するadd_filter( 'フィルター名', 'コールバック関数' );
を使って、フィルターフックにコールバック関数を追加する
次のような流れで処理されます。
apply_filters( 'hook_name', $value );
が実行される- そのフックに登録されたコールバック関数が
$value
を引数として受け取る - 受け取った
$value
を加工・変更して返す - すべての登録関数の処理が完了すると、
apply_filters()
の呼び出し元の処理が続行される
コールバック関数
コールバック関数(Callback Function)とは、他の関数に引数として渡される関数のことです。その名の通り、呼び出されて実行される関数です。
なぜフックを使うのか
テーマファイルをカスタマイズする方法のひとつとして、テンプレートファイルを子テーマのフォルダにコピーし、複製したファイルを編集する手法が一般的に知られていますが、この手法はお勧めできません。その理由は、親テーマがバージョンアップされた際、子テーマにコピーしたファイルには変更が反映されないからです。例えば、親テーマのindex.phpファイルがバージョンアップで機能の追加や仕様変更が行われた場合を考えてみましょう。子テーマ内に同名のindex.phpファイルが存在すると、親テーマのバージョンアップに関わらず子テーマのファイルが読み込まれてしまいます。これにより、新たに追加された機能が利用できない、またはページの表示が崩れるなどの問題が発生する可能性があります。
Lightningでは、index.phpを直接カスタマイズしたり、複製して編集したりすることは、推奨されていません。詳しくは、ベクトル社の「できる!WordPressカスタマイズ #03 WordPressのカスタマイズは子テーマ?プラグイン?」をご覧ください。
コードの記述場所
ページをカスタマイズするためのコードの記述場所としては、子テーマのfunctions.phpファイルやCode Snippetsなどのプラグインが挙げられます。
プラグインを利用すると、テーマを変更してもカスタマイズが維持されますが、今回のカスタマイズはLightningに特化したものであるため、子テーマのfunctions.phpでも特に問題ありません。
<?phpと?>
テンプレートファイル内でよく見かける <?php
と ?>
は、PHPタグです。この2つのタグの間にPHPコードを挿入し、HTMLコードと組み合わせて使います。
PHP(Hypertext Preprocessor)は、「HTMLを生成する前に処理を行うプログラム」という役割を持つサーバーサイドのスクリプト言語です。サーバーがPHPスクリプトを実行し、その結果を含むHTMLをブラウザに送信します。そのため、PHPは、動的なコンテンツの生成やWordPressの機能を利用するために用いられます。
検索ページのテンプレート
Lightning バージョン 15.10.3 Generation 3の検索ページで使用されているテンプレートファイル「index.php」を見ていきましょう。
1.名前空間
// index.php から抜粋
use VektorInc\VK_Breadcrumb\VkBreadcrumb;
名前空間(Namespace)は、自分のコードと、PHPの組み込みまたはサードパーティのクラス/関数/定数の名前が衝突するのを防ぐための手段です。完全修飾名(Fully Qualified Name)を指定することで、どの名前空間内の要素を使用するのかを明示的に指定します。詳しくは、名前空間の概要と名前空間の使用法: エイリアス/インポートを参照してください。
2.ヘッダー
// index.php から抜粋
lightning_get_template_part( 'header' );
lightning_get_template_part( 'テンプレート名' );
は、テンプレートパーツを読み込むための関数です。この場合、header.phpが読み込まれます。header.phpには、htmlタグからbodyの開始タグまでのコードが含まれています。
3.サイトヘッダー
// index.php から抜粋
do_action( 'lightning_site_header_before', 'lightning_site_header_before' );
if ( apply_filters( 'lightning_is_site_header', true, 'site_header' ) ) {
lightning_get_template_part( 'template-parts/site-header' );
}
do_action( 'lightning_site_header_after', 'lightning_site_header_after' );
サイトのロゴやヘッダーナビゲーションを表示します。
サイトヘッダー(header
タグ)の前後にアクションフックが用意されており、独自のコードを挿入できるようになっています。
もしlightning_is_site_header
フィルターがtrue
を返すなら、site-header.phpを読み込みます。このフィルターは、デフォルトでは表示が有効に設定されていますが、false
を返すようにすれば、テンプレートは読み込まれないので、サイトヘッダーを非表示にできるという仕組みです。
LP(Landing Page)の作成時に活用できる!サイトヘッダーの非表示
フィルターがif
文の条件になっている場合は、false
を返す__return_false()
が便利です。
// サイトヘッダーを非表示にする
add_filter( 'lightning_is_site_header', '__return_false' );
TIPS
HTML要素を非表示にする方法としてCSSを使用すると、要素自体はページに読み込まれますが、PHPを使えば、そもそもHTML要素を出力しないようにできます。
4.フロントページの場合
// index.php から抜粋
if ( is_front_page() ) {
if ( apply_filters( 'lightning_default_slide_display', true ) ) {
LTG_G3_Slider::display_html();
}
}
もし現在のページがフロントページで、lightning_default_slide_display
フィルターがtrue
を返すなら、LTG_G3_Slider
クラスのdisplay_html()
メソッドを実行します。 LTG_G3_Slider
は、class-ltg-g3-slider.phpで定義されています。
TIPS
メソッドが定義されているファイルを探したい場合は、GitHubのCode検索機能を使用すると素早く見つけられます。ただし、この機能を利用するにはアカウントが必要です。VS Codeの検索機能も活用できます。「VS CodeからWordPressを編集してみる」を参考にしてください。
5.フロントページ以外の場合
現在のページがフロントページではない場合、何をするかが、この2行の間に書かれています。
// index.php から抜粋
<?php if ( ! is_front_page() ) : ?>
<?php endif; ?>
5-1.ページヘッダー
// index.php から抜粋
do_action( 'lightning_page_header_before', 'lightning_page_header_before' );
if ( apply_filters( 'lightning_is_page_header', true, 'page_header' ) ) {
lightning_get_template_part( 'template-parts/page-header' );
}
do_action( 'lightning_page_header_after', 'lightning_page_header_after' );
page-header.phpを読み込み、ページヘッダーを表示します。
カスタマイズ1:ショップ検索ページのヘッダータイトルを「ショップ検索」に変更する
page-header.phpには、lightning_page_header_title_html
フィルターが用意されているので、ページヘッダータイトルを変更できます。
// page-header.php から抜粋
$page_header_title_html = '<' . $page_title_tag . ' class="page-header-title">' . $page_header_title . '</' . $page_title_tag . '>';
echo wp_kses( apply_filters( 'lightning_page_header_title_html', $page_header_title_html ), $allowed_html );
このフィルターを使って、ショップの検索ページのヘッダー タイトルをショップ検索に書き換えてみましょう。
フィルターフックに無名関数を登録します。ightning_page_header_title_html
is_search()
を使って現在のページが検索ページかどうかを判定し、get_query_var()で投稿タイプがshopかどうかを確認したうえで、$page_header_title_htmlを書き換えます。
add_filter( 'lightning_page_header_title_html', function( $page_header_title_html ) {
// 現在のページが検索ページであり、検索対象の投稿タイプが 'shop' の場合
if ( is_search() && get_query_var('post_type') === 'shop' ) {
// ページヘッダーのタイトルを「ショップ検索」に変更
$page_header_title_html = '<h1 class="page-header-title">ショップ検索</h1>';
}
// 変更後のタイトルを返す
return $page_header_title_html;
} );
TIPS
WordPressは、「クエリが実行される前」にfunction.phpをロードするため、function.phpにConditional Tags(条件付きタグ)を記述しただけでは機能しません。条件付きタグを使う場合は、フックを利用し、「クエリが実行された後」に条件を判定する必要があります。
5-2.パンくずリスト
// index.php から抜粋
do_action( 'lightning_breadcrumb_before', 'lightning_breadcrumb_before' );
if ( apply_filters( 'lightning_is_breadcrumb_position_normal', true, 'breadcrumb_position_normal' ) ) {
if ( apply_filters( 'lightning_is_breadcrumb', true, 'breadcrumb' ) ) {
$vk_breadcrumb = new VkBreadcrumb();
$breadcrumb_options = array(
'id_outer' => 'breadcrumb',
'class_outer' => 'breadcrumb',
'class_inner' => 'container',
'class_list' => 'breadcrumb-list',
'class_list_item' => 'breadcrumb-list__item',
);
$vk_breadcrumb->the_breadcrumb( $breadcrumb_options );
}
}
do_action( 'lightning_breadcrumb_after', 'lightning_breadcrumb_after' );
パンくずリスト(breadcrumb)の前後にアクションフックが用意されており、独自のコードを挿入できるようになっています。
特定の条件を満たす場合にのみパンくずリストを表示します。
lightning_is_breadcrumb_position_normal
フィルターを通じて、通常の位置にパンくずリストを表示するかどうかを確認します。デフォルトでは表示が有効に設定されています。- パンくずリストの表示が有効である場合、
VkBreadcrumb
クラスのインスタンス$vk_breadcrumb
を生成し、パンくずリストのオプション$breadcrumb_options
を設定します。次に、the_breadcrumb()
メソッドを呼び出してパンくずリストを表示します。
VkBreadcrumb
は、/wp-content/themes/lightning/vendor/vektor-inc/vk-breadcrumb/src/VkBreadcrumb.phpで定義されています。
6.サイトボディ
// index.php から抜粋
<?php do_action( 'lightning_site_body_before', 'lightning_site_body_before' ); ?>
<div class="<?php lightning_the_class_name( 'site-body' ); ?>">
<?php do_action( 'lightning_site_body_prepend', 'lightning_site_body_prepend' ); ?>
<div class="<?php lightning_the_class_name( 'site-body-container' ); ?> container">
<div class="<?php lightning_the_class_name( 'main-section' ); ?>" id="main" role="main">
<?php do_action( 'lightning_main_section_prepend', 'lightning_main_section_prepend' ); ?>
<?php
if ( apply_filters( 'lightning_is_main_section_template', true, 'main_section_template' ) ) {
if ( lightning_is_woo_page() ) {
lightning_get_template_part( 'template-parts/main-woocommerce' );
} else {
if ( apply_filters( 'lightning_is_singular', is_singular() ) ) {
lightning_get_template_part( 'template-parts/main-singular' );
} else {
if ( is_404() ) {
lightning_get_template_part( 'template-parts/main-404' );
} else {
lightning_get_template_part( 'template-parts/main-archive' );
}
}
}
}
?>
<?php do_action( 'lightning_main_section_append', 'lightning_main_section_append' ); ?>
</div><!-- [ /.main-section ] -->
<?php
do_action( 'lightning_sub_section_before', 'lightning_sub_section_before' );
if ( lightning_is_subsection() ) {
if ( lightning_is_woo_page() ) {
do_action( 'woocommerce_sidebar' );
} else {
lightning_get_template_part( 'sidebar', get_post_type() );
}
}
do_action( 'lightning_sub_section_after', 'lightning_sub_section_after' );
?>
</div><!-- [ /.site-body-container ] -->
<?php do_action( 'lightning_site_body_append', 'lightning_site_body_append' ); ?>
</div><!-- [ /.site-body ] -->
条件に応じて異なるテンプレートを読み込み、メインコンテンツとサイドバーを表示します。
カスタマイズ2:各フロアの検索結果を表示する際に、フロアマップも表示する
lightning_main_section_prepend
フックを使って、メインセクションの先頭にフロアマップを追加してみましょう。
add_action('lightning_main_section_prepend', function() {
// 現在のページが検索ページである場合の処理
if (is_search()) {
// shop_floorのタームと対応する画像IDを関連付ける配列を設定
// 画像IDは、[管理画面|メディア]を開き、対象の画像をマウスオーバーすると、確認できます
$terms_to_attachments = array(
'b2' => 1,
'b1' => 2,
'1f' => 3,
'2f' => 4,
'3f' => 5,
'4f' => 6,
'rf' => 7,
);
// クエリ変数 'shop_floor' を取得
$shop_floor = get_query_var('shop_floor');
// クエリ変数の値に対応する画像IDがある場合は画像を取得して出力
if (isset($terms_to_attachments[$shop_floor])) {
echo wp_get_attachment_image($terms_to_attachments[$shop_floor], 'large');
}
}
});
このコードは、shop_floor
というクエリ変数(Query Variables)の値に応じて、適切な画像を表示します。
lightning_main_section_prepend
アクションフックに無名関数を登録します。is_search()
を使用して、現在のページが検索ページかどうかを判定し、以下の処理をします。shop_floor
のターム(b2
,b1
,1f
,2f
,3f
,4f
,rf
)と対応する画像IDを関連付ける配列を定義します。- 現在のクエリから
shop_floor
の値を取得します。 isset()
を使用して、shop_floor
の値に対応する画像IDが存在することを確認し、wp_get_attachment_image()を使用して画像を表示します。
7.フッター上部
// index.php から抜粋
<?php if ( is_active_sidebar( 'footer-before-widget' ) ) : ?>
<div class="site-body-bottom">
<div class="container">
<?php dynamic_sidebar( 'footer-before-widget' ); ?>
</div>
</div>
<?php endif; ?>
フッター上部のウィジェット(footer-before-widge)を表示します。dynamic_sidebar() は、ウィジェットを表示するための関数です。
8.サイトフッター
// index.php から抜粋
do_action( 'lightning_site_footer_before', 'lightning_site_footer_before' );
if ( apply_filters( 'lightning_is_site_footer', true, 'site_footer' ) ) {
lightning_get_template_part( 'template-parts/site-footer' );
}
do_action( 'lightning_site_footer_after', 'lightning_site_footer_after' );
site-footer.phpを読み込み、フッターナビゲーション、フッターウィジェット、コピーライトを表示します。
「Powered by ・・・」を非表示にする
site-footer.phpファイルを見ると、コピーライトの表示には、lightning_the_footer_copyight()
という関数が使用されていることが分かります。この関数は、template-tags.phpで定義されていて、「Powered by WordPress & Lightning Theme by Vektor,Inc. technology.」というテキストをカスタマイズするためのlightning_footerPoweredCustom
フィルターが用意されています。
// /template-tags.php から抜粋
// Powered.
$lightning_footer_powered = __( '<p>Powered by <a href="https://wordpress.org/">WordPress</a> & <a href="https://wordpress.org/themes/lightning/" target="_blank" title="Free WordPress Theme Lightning"> Lightning Theme</a> by Vektor,Inc. technology.</p>', 'lightning' );
echo wp_kses_post( apply_filters( 'lightning_footerPoweredCustom', $lightning_footer_powered ) );
空の文字列を返す__return_empty_string()を使うと、簡潔なコードになります。
// 「Powered by ・・・」を非表示にする
add_filter( 'lightning_footerPoweredCustom', '__return_empty_string' );
フィルターフックを使うと$value
の値が書き換わると勘違いしていました
apply_filters( 'hook_name', $value );
の呼び出し自体は、$value
の値を変更しません。フィルターした値を返すだけです。
PHPでは、通常の引数渡しは「値渡し(by value)」 となるため、コールバック関数内で$value
を変更しても、元の$value
には影響を与えません。
実際に$value
の値を変更するには、$value = apply_filters( 'hook_name', $value );
のように代入する必要があります。
9.フッター
// index.php から抜粋
lightning_get_template_part( 'footer' );
footer.phpを読み込み、bobyタグとhtmlタグを閉じます。
参考サイト
アクションフックを使ったカスタマイズ方法について詳しく解説されています。
初心者向けのオンライン学習サービスで、無料で学べるコースが多数用意されています。
Lightning G3 Pro Unit
アクションフックの場所をカスタマイザーで確認できます。
詳しくは「トップページ / 個別ページ(singular)のメインエリアの表示内容をプログラムで直接書き込む」をご覧ください。
まとめ
たくさんのファイルが呼び出されているため、複雑に感じたかもしれません。私自身、初めてPHPファイルを見たときは全く理解できませんでしたが、学習を続けるうちに全体の構造を大まかに把握できるようになりました。
そこで、テンプレートファイルを読み解くためのポイントをまとめました。
- テンプレートファイルか、クラスを定義するファイルかを区別する
- どの部分がHTMLで、どの部分がPHPなのかを意識する
get_template_part()
で読み込まれるファイルをたどる- WordPressの組み込み関数をチェックする
- 条件分岐タグの使われ方を理解する
var_dump()
を使って変数の中身を確認する
この記事が、みなさんの学習の助けになれば嬉しいです。
お世話になっております。
カスタマイズ3:「Powered by ・・・」を非表示にする
この部分でつまずいていました。
_g3/template-parts/site-foote.php ファイルを見ると、コピーライトの表示には、lightning_the_footer_copyight() という関数が使用されていることが分かっていましたが、これを削除しても表示が消えなくて止まっていました。
もう一つ深めて学ぶ必要があると感じています。
勉強になります。