WordPressにおけるカスタマイズの基礎(アクションとフィルター)

2020年1月9日

いきなりプラグインのカスタマイズに入る前に、「プラグインでのWordPressのカスタマイズのやり方」についてちょっと触れてみたいと思います。

WordPressでのカスタマイズのポイント

WordPressは外部からアクセスがある度に(キャッシュを使用しない限り)、必要なファイルを読み込み、「事前に設定された処理ステップ」を踏まえて最終的なアウトプットへと処理が進められていきます。

WordPressはこの「事前に設定された処理ステップ」の中に、ユーザーが自由に処理を追加できるよう、「フィルター」や「アクション」といったフックを挟み込んでいます。

この説明では抽象的なので、リンゴの皮剥き手順を例として考えてみよう。

基本のリンゴの皮剥き手順は以下の通りとします。(異論は認めるけど無視します)

基本のリンゴの皮剥き手順

STEP1:リンゴを手に持つ

STEP2:包丁を手に持つ

STEP3:
・リンゴの皮剥き条件【皮の太さ:2㎝、皮の厚さ:2mm、剥く方向:円を描くように】
・「リンゴの皮剥き条件」に従いリンゴの皮剥きをする

しかし、このままではこのリンゴの皮剥き手順に何のカスタマイズもできないので、「リンゴを手に持った後にするアクション」「包丁を手に持つ前にするアクション」「リンゴの皮剥きフィルター」というカスタマイズできるポイントを追加してみます。

カスタマイズ可能なリンゴの皮剥き手順

STEP1:リンゴを手に持つ

追加STEP1-1:「リンゴを手に持った後にするアクション」に関数が追加されていればそれを実行

追加STEP2-0:「包丁を手に持つ前にするアクション」に関数が追加されていればそれを実行

STEP2:包丁を手に持つ

STEP3:
・リンゴの皮剥き条件【皮の太さ:2㎝、皮の厚さ:2mm、剥く方向:円を描くように】
・追加STEP3-0: 「リンゴの皮剥きフィルター」に関数が追加されていればそれで「リンゴの皮剥き条件」を上書きする
・「リンゴの皮剥き条件」に従いリンゴの皮剥きをする

この青と緑で追加したSTEPがあることで、「リンゴの皮剥き手順」をカスタマイズしたいユーザーは、「リンゴを手に持った後にするアクション」「包丁を手に持つ前にするアクション」「リンゴの皮剥きフィルター」に独自の処理を追加することで、様々ななカスタマイズが可能となります。

WordPressも同様に、ユーザーのアクセスから最終的なアウトプットまでの各段階でこのような「カスタマイズ可能なステップ」を準備してくれるので、それを利用しプラグインを作成することとなります。

そしてこの「カスタマイズ可能なステップ」のことをフックと呼んでいます。

カスタマイズの種類:アクションとフィルター

先ほどの「リンゴの皮剥き手順」では、カスタマイズ可能なポイント(フック)として、青で示した「アクション」緑で示した「フィルター」の2種類があることに気付いてもらえたと思います。

フィルターについて

「リンゴの皮剥きフィルター」では、「リンゴの皮剥き」で使用する事前に設定されたパラメータを上書きするためのフィルターです。このようにフィルターは(基本的には)「何かの関数の処理を行う上で、引数の値や、最終的な出力の値をカスタマイズするためのステップ」と考えてもらえばよいと思います。

アクションについて

アクションは、フィルターと異なり「特定の関数の内部処理についてカスタマイズを行う」ものではありません。

例えば「管理画面にアクセスした後で行うアクション」というアクションに「ログインユーザーが編集者であれば、編集者用のメッセージをダッシュボードに表示」という様に、「特定の状況で行う処理を追加するためのステップ」と考えてもらえればよいと思います。

WordPressで事前に用意されたアクション・フィルターフックについて

WordPressでは以下のように様々なアクションやフィルターが事前に準備されています。

プラグイン API/アクションフック一覧 – WordPress Codex 日本語版 

プラグイン API/フィルターフック一覧 – WordPress Codex 日本語版 

それぞれのアクション・フィルターフックにどのような処理を追加すべきかおおよそ決まっていますので、自分が行いたい処理はどのアクション・フィルターフックを利用するのか上記サイトで確認したり、先人たちのプラグインを読みつつ勉強されると良いと思います。

このサイトでも、アクション・フィルターフックをどんどん利用しますので興味のある方は見て見てください。(そして疑問に思う事がありましたら教えてください)

アクション・フィルターフックへの処理の追加方法について

アクション・フィルターフックに独自の処理を追加することでWordPressをカスタマイズすることができることを上で説明しました。

それでは、具体的な追加の方法について書いてみます。

アクションフックへの処理追加方法

アクションへの処理の追加は、add_action()関数を使用して行います。

例えば、WordPressのカスタマイズをしたことがある方なら一度は行っていると思われる「カスタム投稿タイプの追加」です。


add_action('init', 'add_photo_post_type');
function add_photo_post_type() {
    //photo投稿タイプを追加するプログラムを記載
}

ここでは、initアクションフックに、add_photo_post_type()関数(photo投稿タイプを追加する処理)を追加しています。

その為、ユーザーがWordPressで作成されたサイトを見たときにWordPressが行う一連の処理ステップの中で「initアクションフックの実行」ステップに来ると、photo投稿タイプが登録されます。

つまり、このinitアクションフックの実行ステップより前の段階では「photo投稿タイプ」は存在しないので、initアクションフックより前の処理ステップの中で「photo投稿タイプ」に関する処理を行うと「そんな投稿タイプはねえ!」とWordPressに怒られることになります

add_action関数は一般的には以下の通りです。

add_action( 'アクション名’, '追加処理させたい関数名’int $priority = 10, int $accepted_args = 1 )

$priorityや$accepted_argsは無くても構いません。

$priorityは、同じアクションフックに追加された他の処理と比較して早く処理を行った有、遅く処理を行いたければ$priorityの値を減増させます。(少ない方が早い段階で処理されます)

アクションフックの中には引数を求める物もあります。 このようなアクションフックを利用する際に4番目の引数($accepted_args)を使います。例えばアクションフックに登録された処理を実行する関数としてdo_action()があるのですが、WordPressのどこかに

do_action( 'calculate-area', $width, $height );

と書かれていた場合、この「calculate-area」アクションフックは2つの引数($width, $height)を利用します。この場合は、

/*
calculate_areaアクションを実行する部分で以下のようになっている場合。
do_action( 'calculate_area', $width, $height );
*/

add_action( 'calculate_area', 'doubled', 10, 2 );
function doubled( $width, $height){
    echo '縦横の長さを2倍にすると' . $width * 2 * $height * 2 . 'となります(単位省略)';
}

のようにadd_action()の4番目の引数を2に指定し、処理を追加する関数に2つの引数を追加して利用することになります。

フィルターフックへの処理方法の追加

基本的にはアクションフックへの処理方法の追加と同じやり方です。使用する関数は、アクションフックの場合がadd_action()関数であったのに対し、フィルターフックではadd_filter()関数を使用します。

add_filter()関数で利用される引数は以下の通りです。

add_filter( 'フィルター名’, '追加処理させたい関数名’, $priority = 10, $accepted_args = 1 )

$priority, $accepted_argsの扱いについても、add_action()関数と同じです。

例えば、the_content()関数での出力の最後に、常に宣伝文句を追加したい場合は以下のように行います。

the_content()関数はwp-includes\post-template.phpファイルで定義されていて、そこには以下のように書かれています。

/**
 * Display the post content.
 *
 * @since 0.71
 *
 * @param string $more_link_text Optional. Content for when there is more text.
 * @param bool   $strip_teaser   Optional. Strip teaser content before the more text. Default is false.
 */
function the_content( $more_link_text = null, $strip_teaser = false ) {
	$content = get_the_content( $more_link_text, $strip_teaser );
	/**
	 * Filters the post content.
	 *
	 * @since 0.71
	 *
	 * @param string $content Content of the current post.
	 */
	$content = apply_filters( 'the_content', $content );
	$content = str_replace( ']]>', ']]& gt;', $content );//←ここの& gt;は実際にはスペースはありません。
	echo $content;
}

出力前にapply_filters()関数を使用し($content = apply_filters( 'the_content’, $content )の部分)、the_contentフィルターに追加されたフィルターで$contentの内容をカスタマイズできるようにしています。

※ここでthe_content()関数に利用されているフィルターがthe_contentという名称なのは「たまたま」です。あらゆる関数においてそこで同じ名前のフィルターが利用されているわけではありません。

これを踏まえて以下のようにフィルターフックを利用したカスタマイズを行うことができます。

add_filter( 'the_content', 'add_extra_text_to_the_content' );
function add_extra_text_to_the_content( $content ){
    return $content .= '<p class="aadvertisement">これは広告です</p>';
}

他プラグインのアクション・フィルターフックについて

さて以上でWordPressのカスタマイズにはアクション・フィルターフックを利用することがわかりました。

さらに、すぐ上のフィルターフックの使い方の部分で書いたように、WordPressで利用される関数においてカスタマイズできるかどうかは、その関数が定義されているファイルとその定義部分にdo_action()関数や、apply_filters()関数があるかを確認することで判断できることもわかりました。

更に加えて、公開されているプラグインの中には、ユーザーがカスタマイズしやすい用に、至るところに独自のアクション・フィルターフックを準備してくれているプラグインもあります。

例えば有名なContact Form 7プラグインには、バリデーション用の関数がありますが、その中にそれぞれのバリデーションをカスタマイズできるようにフィルターフックを準備してくれています。

contact-form-7\includes\submission.php

private function validate() {
    if ( $this->invalid_fields ) {
        return false;
    }

    require_once WPCF7_PLUGIN_DIR . '/includes/validation.php';
    $result = new WPCF7_Validation();

    $tags = $this->contact_form->scan_form_tags();

    foreach ( $tags as $tag ) {
        $type = $tag->type;
        $result = apply_filters( "wpcf7_validate_{$type}", $result, $tag );
    }

    $result = apply_filters( 'wpcf7_validate', $result, $tags );

    $this->invalid_fields = $result->get_invalid_fields();

    return $result->is_valid();
}

これを使用し、例えば電話番号が080から始まっているものだけ許可する場合は、

add_filter( 'wpcf7_validate_tel', 'my_custom_tel_validation', 11, 2 );
function my_custom_tel_validation( $result, $tags ){
    $type = $tag['type'];
    $name = $tag['name'];
    $_POST[$name] = trim( strtr( (string) $_POST[$name], "\n", " " ) );
    if( 'tel' == $type || 'tel*' == $type ){
        if( !preg_match( '/\A080/', $name, $matches ) ){
            $result['valid'] = false;
            $result['reason'] = array( $name => '080から始まっていません' );
        }
    }
    return $result;
}

こんな感じで、独自のフィルターを追加することができます。

現在使用しているプラグインの機能になにか追加処理をしたい場合は、プラグイン内の関数などを検索し、アクション・フィルターフックの有無を探してみると良いと思います。

基本

Posted by webmaster