きっかけと課題の発見
WordPressのブログで記事一覧ページを見ていたとき、ひとつの疑問が浮かびました。記事の抜粋文(entry-summary)が表示されているけれど、読者にとってはタグの方が記事の内容を把握しやすいのではないか。
特に技術ブログの場合、「この記事はReactについて書かれている」「データベース関連の内容だ」といった情報の方が、文章の冒頭部分よりも価値があります。まるで本屋さんで本を探すとき、最初の数行を読むよりもジャンル分けされた棚を見る方が効率的なのと同じです。
そこで、entry-summaryをタグリンクに置き換える仕組みを作ってみることにしました。
基本方針の決定
置き換える際の表示条件を決める必要がありました。すべてのタグを表示すると画面が煩雑になってしまいます。そこで以下の条件を設定しました。
複数の記事で使われているタグのみを表示する。これにより、一度だけ使われた特殊なタグは除外され、そのブログでよく扱われるテーマに関するタグだけが表示されます。
記事数の多い順にソートして、人気の高いトピックを優先的に表示する。
表示するタグ数は最大5つまでに制限し、画面の見やすさを保つ。
表示形式は「#タグ名(記事数)」のハッシュタグスタイルを採用しました。
functions.phpでの初期実装
最初はテーマのfunctions.phpファイルに実装しました。WordPressのフィルター機能1を使って、抜粋文が生成される際にタグリンクに置き換える方法です。
function replace_entry_summary_with_tags($excerpt) {
// 記事一覧ページでのみ動作させる
if (is_single() || is_page()) {
return $excerpt;
}
global $post;
$posttags = get_the_tags($post->ID);
// タグがない場合は元の抜粋を返す
if (!$posttags) {
return $excerpt;
}
$tag_data = array();
// 複数記事で使われているタグのみを収集
foreach ($posttags as $tag) {
if ($tag->count > 1) {
$tag_data[] = array(
'count' => $tag->count,
'name' => $tag->name,
'link' => get_tag_link($tag->term_id),
'term_id' => $tag->term_id
);
}
}
// 表示するタグがない場合は元の抜粋を返す
if (empty($tag_data)) {
return $excerpt;
}
// 記事数の多い順にソート
usort($tag_data, function ($a, $b) {
return $b['count'] - $a['count'];
});
// 最大5つまでに制限
$tag_data = array_slice($tag_data, 0, 5);
// タグリンクのHTMLを生成
$tag_links = array();
foreach ($tag_data as $tag) {
if (!is_wp_error($tag['link'])) {
$tag_links[] = '<a class="tag-link tag-link-' . $tag['term_id'] . ' border-element" href="' . esc_url($tag['link']) . '">#' . esc_html($tag['name']) . '(' . $tag['count'] . ')</a>';
}
}
if (!empty($tag_links)) {
return '<div class="entry-tags-summary">' . implode(' ', $tag_links) . '</div>';
}
return $excerpt;
}
add_filter('get_the_excerpt', 'replace_entry_summary_with_tags');
add_filter('wp_trim_excerpt', 'replace_entry_summary_with_tags');
Code language: PHP (php)
この実装では、get_the_excerptとwp_trim_excerptの2つのフィルター2を使用しています。get_the_excerptは手動で設定された抜粋文、wp_trim_excerptは自動生成される抜粋文をそれぞれ処理します。
重要なポイントは、記事詳細ページでは通常の抜粋を表示し続けることです。is_single()やis_page()でページタイプを判定し、記事一覧ページでのみタグ置き換えを実行します。
プラグイン化の決断と実装
functions.phpでの実装が成功した後、この機能をプラグイン化することにしました。理由は3つあります。
テーマを変更しても機能が維持される点。functions.phpの内容はテーマと一緒に失われてしまいますが、プラグインなら独立して存在できます。
他のサイトでも使い回せる汎用性。一度作成すれば、複数のサイトで活用できます。
管理画面からの設定変更が可能になる点。コードを直接編集する必要がなくなります。
プラグイン化では、オブジェクト指向プログラミングの手法3を採用し、機能を整理して実装しました。
class EntrySummaryTagReplace {
private $options;
public function __construct() {
add_action('init', array($this, 'init'));
add_action('admin_init', array($this, 'admin_init'));
add_action('admin_menu', array($this, 'add_plugin_page'));
add_action('wp_head', array($this, 'add_tag_summary_styles'));
// デフォルト設定
$this->options = get_option('entry_summary_tag_options', array(
'max_tags' => 5,
'min_count' => 2,
'show_count' => true,
'enable_plugin' => true
));
}
Code language: PHP (php)
クラス化することで、設定値を$this->optionsとして管理し、各メソッドからアクセスできるようになりました。これにより、コードの保守性が大幅に向上しています。
管理画面の実装
WordPressの設定API4を使用して、管理画面を作成しました。ユーザーが簡単に設定を変更できるインターフェースです。
public function add_plugin_page() {
add_options_page(
'Entry Summary Tag Replace設定',
'タグ置き換え',
'manage_options',
'entry-summary-tag-admin',
array($this, 'create_admin_page')
);
}
Code language: PHP (php)
設定項目は以下の通りです。
プラグインの有効・無効切り替え。機能を一時的に停止したい場合に便利です。
表示するタグの最大数。1から20まで設定可能で、画面の表示に合わせて調整できます。
表示する最小記事数。何記事以上で使われているタグを表示するかを設定します。
記事数表示の有無。「#タグ名(5)」の記事数部分を表示するかどうかを選択できます。
これらの設定は、register_setting、add_settings_section、add_settings_fieldといったWordPressの標準APIを使用して実装しています。
CSSの最適化
初期実装では汎用的なCSSを用意していましたが、実際の使用環境に合わせて最適化を行いました。
.entry-tags-summary {
margin: 0;
line-height: 1.5;
}
.entry-tags-summary .tag-link {
display: inline-block;
margin: 2px 4px 2px 0;
padding: 0;
background-color: transparent;
border: transparent;
color: var(--accent);
text-decoration: underline;
font-size: 0.9em;
}
.entry-tags-summary .tag-link:hover {
text-decoration: none;
}
Code language: CSS (css)
最初は背景色やボーダー、パディングなどの装飾を多用していましたが、テーマとの統一性を重視してシンプルな設計に変更しました。CSS変数のvar(--accent)5を使用することで、テーマのカラーパレットに自動的に適応します。
この変更により、どのテーマでも自然に溶け込むデザインになりました。
技術的な工夫と注意点
開発過程で特に注意した技術的なポイントがいくつかあります。
セキュリティ対策として、出力する文字列にはすべてesc_html()やesc_url()などのエスケープ処理6を適用しています。これにより、悪意のあるコードの実行を防げます。
エラーハンドリングでは、is_wp_error()を使用してリンク生成エラーをチェックし、問題がある場合は該当するタグをスキップします。
パフォーマンスを考慮し、管理画面以外では不要な処理を実行しないよう条件分岐を設けています。
プラグインの削除時には設定データもクリーンアップする仕組みを実装し、データベースの肥大化を防いでいます。
実装結果と効果
完成したプラグインは、以下の特徴を持っています。
記事一覧ページでは関連性の高いタグが自動的に表示され、読者は記事の内容を素早く把握できます。記事詳細ページでは従来通りの抜粋文が表示されるため、既存の機能を損なうことはありません。
管理画面からの直感的な設定変更により、サイトの特性に合わせたカスタマイズが可能です。テーマを変更しても機能が維持されるため、サイトの運営において長期的な安定性を提供します。
functions.phpからプラグインへの発展により、WordPressの拡張機能開発における一連の流れを体験できました。小さな改善から始まり、段階的に機能を拡張していく開発手法は、実際のプロジェクトでも活用できる手法です。
- WordPressのフィルター機能は、特定のタイミングでデータを加工・変更できる仕組みです。add_filter()でフック名と関数を登録すると、該当するタイミングで自動的に関数が実行されます。 – Plugin API/Filter Reference – WordPress Codex
- get_the_excerptは投稿編集画面で手動設定された抜粋文を処理し、wp_trim_excerptは抜粋文が設定されていない場合に本文から自動生成される抜粋文を処理します。両方をフックすることで、すべてのパターンに対応できます。 – get_the_excerpt() – WordPress Developer Resources
- オブジェクト指向プログラミング(OOP)は、関連する変数と関数をクラスという単位でまとめる手法です。PHPではclass構文を使用し、データ(プロパティ)と処理(メソッド)を一つにまとめることで、コードの再利用性と保守性が向上します。 – Classes and Objects – PHP Manual
- WordPress Settings APIは、管理画面での設定項目を統一的に管理するためのフレームワークです。register_setting()、add_settings_section()、add_settings_field()を組み合わせることで、セキュアで一貫性のある設定画面を作成できます。 – Settings API – WordPress Developer Resources
- CSS変数(カスタムプロパティ)は、CSS内で再利用可能な値を定義する仕組みです。–accent のように「–」で始まる名前で定義し、var(–accent)で参照します。これによりテーマ全体の色管理が統一され、保守性が向上します。 – Using CSS custom properties (variables) – MDN
- エスケープ処理は、ユーザー入力やデータベースから取得したデータを安全にHTMLに出力するための処理です。esc_html()はHTMLの特殊文字をエンティティに変換し、esc_url()はURLの形式をチェックして無害化します。これによりXSS攻撃を防げます。 – Data Validation – WordPress Developer Resources