ワードプレスの記事中の任意の場所に任意のタグを挿入するためのアイデア

記事中の任意の場所に任意のタグを挿入するための方法です。

あくまでもアイデアですので、これよりも出来の良い方法もあるかもしれませんし、この方法自体完全な方法ではありません。

wordpress-insert-tag

「記事の最初に任意のタグや定型文を挿入する」や「記事の最後に任意のタグや定型文を挿入する」という方法は、プラグインなどもあり簡単に実装することが出来ます。

ただ「記事中」となるとけっこう大変です。

一番簡単な方法は、JavaScript の DOM 操作で挿入することなのですが、サーバー時点、ソースの時点で挿入したい場合はワードプレスの場合 PHP で実行する他ありません。

今回はこのようなパターンを考えます。

2段落目と3段落目の間に h2 タグを挿入。
ただし、すでに記事中に h2 タグが存在している場合は挿入しない。

段落は p タグで管理しているものとします。

HTML
<p>1段落目</p>
<p>2段落目</p>
 
//ここに <h2></h2> を挿入
 
<p>3段落目</p>

以下を functions.php に加えます。

functions.php

function content_plus_h2($the_content) {
    if (strpos($the_content, '<h2') === false && is_single()) {
        $pattern = '/<\/p>/i';
        preg_match_all($pattern, $the_content, $matches, PREG_OFFSET_CAPTURE);
        $result = substr_replace($the_content, '</p><h2></h2>', $matches[0][1][1], strlen('</p>'));
        return $result;
    } else {
        return $the_content;
    }
}
 
add_filter('the_content', 'content_plus_h2');

細かく見ていきます。

1行目

function content_plus_h2($the_content) {

$the_content は記事本文を表します。
後からワードプレスのフィルターフックを使うために関数化します。フォルターフックについては以下のページが参考になりました。

参考:WordPressのフィルターフックで投稿を全て夢オチにする方法と、真面目な使い方

2行目

if (strpos($the_content,'<h2') === false && is_single()) {

「記事本文に <h2 が存在せず(false)、かつ記事ページである」の条件分離です。

<h2> としてしまっても良いのですが、h2 タグに class 等設定されていても大丈夫なように、中途半端ですがこのような判別法となってます。
厳密に判別したい場合は、正規表現を使い条件を細かく設定してください。

3行目

$pattern = '/<\/p>/i';

正規表現を使います。2段落目の最後は </p> となるはずなので、この閉じタグを探します。

4行目

preg_match_all($pattern, $the_content, $matches, PREG_OFFSET_CAPTURE);

preg_match_all とそのオプションであるオフセット値(何文字目に出てくるか)の取得を使います。

最初から数えて2番目の </p> が何文字目であるかを計測します。

参考:n番目に文字列が現れる場所を探す
参考:preg_match_all

5行目

$result = substr_replace($the_content, '</p><h2></h2>', $matches[0][1][1], strlen('</p>'));

$matches[0][1][1] がポイントです。

詳しくは上記ページを参照にしてもらえればと思いますが、PREG_OFFSET_CAPTURE を設定した場合、配列 $matches[0][n][1] にオフセット値が入ります。n は何番目の </p> であるかを示します。

もし、5番目の </p> 以降に挿入したければ n を 4 とします。(0 が1番目です)$matches[0][1][1] は2番目の </p> となります。strlen('</p>') は文字の長さ(バイト)を示します。

2番目の </p> から </p> の文字数分を数えて、その部分を </p><h2></h2> と入れ替える(substr_replace)という命令となります。

7-9行目

} else {
    return $the_content;
}

2行目の if 文で弾かれたパターンの場合、そのまま the_content を返すようにしておきます。

12行目

add_filter('the_content', 'content_plus_h2');
最後に関数 content_plus_h2() を the_content が実施されたことをフックに実行します。

まとめ

若干例外処理が足りないのですが、2段落無い記事は存在しない状況下でのコードでしたので、このようなコードとなってます。

もし、例外処理等ある場合は随時追加してください。また、マルチバイト対応も若干怪しいので、日本語等を使う場合はまた別の方法になるかもしれません。

JavaScript のように要素を直接扱えればもっと楽ができるのですが、PHP の場合はそうもいかないので大変です。正規表現でゴリゴリ検索するしかありません。かなり変わっている状況でのタグ挿入でしたが、色々応用の効くコードではないかと思います。