WordPress ライトニングの縦棒を消す方法 (アクションフック版)
前回は「子テーマ」を作成して、親テーマを文字列に変換してからタイトルを置換していました。今回はアクションフック(実際に使用しているのはフィルターフックになります)を使用して違った方法で実装してみます。
今回も引き続き、Udemyさんの以下の講座で勉強させて頂きました。
Udemy
ちゃんと学ぶ、WordPress テーマ開発講座
フック処理について
通常PHPコードはテンプレートファイル等に記述されていて、「読み込まれると同時」に実行されますが、フック処理(関数)は実行するタイミングを指定できる様です。どのタイミングで実行されるかは、英語の資料になりますがこちらに一覧があります。
アクションフックとフィルターフックの違いは、アクションフックがWordpressのテンプレートファイルを切り替えたり等の動作も制御できるのに対して、フィルターフックは「タイトル」が呼ばれた時に文字の色などを変えたり記号を追加したり、主に属性を制御する等の違いがある様です。
タイトル作成に関連するフック処理を調べます
前々回調べた個所をもう一度見てみると、do_action関数で「wp_head」というタイミングでタイトルが作られている様です。
function wp_head() {
/**
* Prints scripts or data in the head tag on the front end.
*
* @since 1.5.0
*/
do_action( 'wp_head' );
}
wp_headをWordpressの開発者サイトで調べてみると、「wp-includes/default-filters.php」というファイルの中にデフォルトで実行されるフック関数が定義されている様です。default-filters.phpファイルを調べてみると、334行目にタイトル作成に関係しそうな名前の関数が登録されています。「add_action」関数の3番目の引数は優先順位を表していて値が小さいほうが優先順位が高い様です。最大値(最低値?)がいくつなのかはよく分かりませんでした。
// Actions.
add_action( 'wp_head', '_wp_render_title_tag', 1 );
add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
add_action( 'wp_head', 'wp_resource_hints', 2 );
add_action( 'wp_head', 'wp_preload_resources', 1 );
add_action( 'wp_head', 'feed_links', 2 );
add_action( 'wp_head', 'feed_links_extra', 3 );
add_action( 'wp_head', 'rsd_link' );
add_action( 'wp_head', 'locale_stylesheet' );
add_action( 'publish_future_post', 'check_and_publish_future_post', 10, 1 );
add_action( 'wp_head', 'wp_robots', 1 );
add_action( 'wp_head', 'print_emoji_detection_script', 7 );
add_action( 'wp_head', 'wp_print_styles', 8 );
add_action( 'wp_head', 'wp_print_head_scripts', 9 );
add_action( 'wp_head', 'wp_generator' );
add_action( 'wp_head', 'rel_canonical' );
add_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );
add_action( 'wp_head', 'wp_custom_css_cb', 101 );
add_action( 'wp_head', 'wp_site_icon', 99 );
add_action( 'wp_footer', 'wp_print_footer_scripts', 20 );
「_wp_render_title_tag」関数は「wp-includes/general-template.php」というファイルの1308行目辺りにある様です。この関数から呼ばれている「wp_get_document_title」関数でタイトルを作成している様です。
function _wp_render_title_tag() {
if ( ! current_theme_supports( 'title-tag' ) ) {
return;
}
echo '<title>' . wp_get_document_title() . '</title>' . "\n";
}
「wp_get_document_title」関数は同じgeneral-template.phpファイルの1176行目辺りにある様です。長い関数なので最初の部分だけコピーしました。この関数内の1188行目にある「pre_get_document_title」というフィルターフックでタイトルを取得している様です。デフォルトでは空文字を返しているので、それ以降の処理が実行されてタイトルが作成されています。このフックで何か文字列を返せばその文字列のまま処理を抜けてくれそうです。
function wp_get_document_title() {
/**
* Filters the document title before it is generated.
*
* Passing a non-empty value will short-circuit wp_get_document_title(),
* returning that value instead.
*
* @since 4.4.0
*
* @param string $title The document title. Default empty string.
*/
$title = apply_filters( 'pre_get_document_title', '' );
if ( ! empty( $title ) ) {
return $title;
}
global $page, $paged;
$title = array(
'title' => '',
);
// If it's a 404 page, use a "Page not found" title.
if ( is_404() ) {
$title['title'] = __( 'Page not found' );
子テーマを作成します
方針が決まりましたので、実装していきます。まずはフック関数を記述するために前回と同じように子テーマを作成します。前回とは名前を変えた方がいいかもしれません。以下の場所に任意の子テーマ名(my-theme等)でフォルダを作成します。
<Wordpress>
└─wp-content
└─themes
└─<ここに作成します>
作成したフォルダ内に、「style.css」というファイルを作成して、以下の様なコメントを書き込みます。最低限コメント内の「Template」項目(親テーマフォルダ名)さえあればWordpressに子テーマとして認識されます。他の項目はテーマの詳細情報として表示されますので、ご自身の状況にあわせて修正してください。
/*
Theme Name: My Theme
Author: yuuji mimura
Description: カスタマイズ版Lightningテーマ
Version: 1.0
Template: lightning
*/
今回は追加で「functions.php」という空のファイルも作成します。全体的には以下の様な構成になります。
wp-content
└─themes
└─my-theme
├─style.css
└─functions.php
最後にフォルダとファイルの所有者を変更しておきます。
chown -R www-data:www-data ./<子テーマフォルダ>
以上で子テーマの作成は終了です。Wordpressでテーマが表示されているのを確認して有効化します。
子テーマを修正します
「functions.php」ファイルを以下の様に修正します。
3行目のコマンドは、「general-template.php」ファイルにある「_wp_render_title_tag」関数の1309行目で、フィルターフック関数が呼び出される前に終了してしまうのを防ぐために定義してあります。12行目のフィルター追加関数の3番目の引数は実行する優先順位で、できるだけ最後に実行する(他の処理で上書きされるのを防ぐ)ために低めの優先順位にしてあります。Lightningの場合は10以下にすると上書きされてしまう様です。4番目の引数はget_title関数に渡す引数の個数になっています。
<?php
// タイトルの書き換え機能を有効化します
add_theme_support('title-tag');
// トップページの場合はサイト名を返します
function get_title($title)
{
return is_front_page() ? get_bloginfo('name') : $title;
}
// フィルターフックを追加します
add_filter('pre_get_document_title', 'get_title', 30, 1);
トップページを表示してみると意図した動作になっている様です。
投稿ページのタイトルも問題ない様ですが、なぜかページヘッダーが表示されてしまう様です。空の子テーマにしても同じ現象が発生する様です。
style.cssファイルに以下のスタイルを追加しました。
.page-header {
display: none;
}
親テーマと同じ外観になりました。
プラグイン化します
今回も子テーマとして実装しましたが、テーマを切り替えると動作しなくなるため、プラグイン化しておくといつでも実行できて便利かもしれません。プラグインを作成するには以下の場所に任意のプラグイン名(my-plugin等)のフォルダとファイルを作成します。(ファイルだけでも動作する様です。) ファイルとフォルダの所有者を「www-data」に変更しておきます。
wp-content
└─plugins
└─my-plugin
└─my-plugin.php
プラグインファイル(例ではmy-plugin.php)の先頭に「<?php」と記入してから、以下の様なコメントを書き込みます。最低限コメント内の「Plugin Name」項目さえあればWordpressにプラグインとして認識されます。他の項目はプラグインの詳細情報として表示されますので、ご自身の状況にあわせて修正してください。
<?php
/*
Plugin Name: My Plugin
Author: yuuji mimura
Description: 個人用プラグイン
Version: 1.0
*/
コメントの下にfunctions.phpに記述した内容をコピーします。PHP文が1つなので終端記号(?>)は省略できます。
<?php
/*
Plugin Name: My Plugin
Author: yuuji mimura
Description: 個人用プラグイン
Version: 1.0
*/
// タイトルの書き換え機能を有効化します
add_theme_support('title-tag');
// トップページの場合はサイト名を返します
function get_title($title)
{
return is_front_page() ? get_bloginfo('name') : $title;
}
// フィルターフックを追加します
add_filter('pre_get_document_title', 'get_title', 30, 1);
以上で終了です。プラグイン画面に表示されているのを確認して、有効化をチェックすると有効になります。
トップ画面を表示してみると正常に動作している様です。
その他
「スマートに実装できます」と言いましたが行数で見るとあまり変わらない様です。
// 【文字列置換版】
<?php
// 出力のバッファリングを有効にします
ob_start();
// 親テンプレートを読み込みます
include(TEMPLATEPATH . "/_g2/header.php");
// 出力内容を取得してバッファをクリアします
$text = ob_get_clean();
// トップページの場合はタイトルを修正します
if (is_front_page()) {
// タイトル名を取得します
$title = get_bloginfo('name');
// タイトルを置換します
$text = preg_replace('/<title>.*?<\/title>/', "<title>{$title}</title>", $text);
}
echo $text;
// 【フィルターフック版】
<?php
// タイトルの書き換え機能を有効化します
add_theme_support('title-tag');
// トップページの場合はサイト名を返します
function get_title($title)
{
return is_front_page() ? get_bloginfo('name') : $title;
}
// フィルターフックを追加します
add_filter('pre_get_document_title', 'get_title', 30, 1);
少し見にくくなりますが、フィルターフックは匿名関数と呼ばれる機能を利用した、以下の様な形式でも記述できる様です。
<?php
// タイトルの書き換え機能を有効化します
add_theme_support('title-tag');
// トップページの場合はサイト名のみを返すフィルターフックを追加します
add_filter('pre_get_document_title', function ($title) {
return is_front_page() ? get_bloginfo('name') : $title;
}, 30, 1);
以上です。よろしかったらお試しください。