WordPressオリジナルテーマを作り始めると、画像URLの取得、SVGの読み込み、パンくず、OGP、投稿カードなど、毎回似た処理を書くことになります。最初に便利関数を用意しておくと、テンプレートが読みやすくなり、あとから修正もしやすくなります。
この記事では、functions.phpへ入れて使える便利関数を10個紹介します。PHP8系を前提に、WordPress標準関数を活用しながら、再利用しやすい形にしています。
SEOタイトル
WordPressオリジナルテーマ開発で最初に作るべき便利関数10選
meta description
WordPressオリジナルテーマ開発で最初に用意したい便利関数を10個紹介。SVG読み込み、asset関数、OGP、パンくず、投稿カードなどをPHP8対応コード付きで解説します。
便利関数のサンプルコード
まずはまとめてコードを掲載します。実際のテーマではfunctions.phpに直接書いても動きますが、量が増える場合はinc/helpers.phpのようなファイルに分けるのがおすすめです。
<?php
declare(strict_types=1);
/**
* テーマ内の画像・CSS・JSなどのURLを返す。
*/
function nines_asset(string $path): string
{
return esc_url(get_template_directory_uri() . '/' . ltrim($path, '/'));
}
/**
* テーマ内ファイルの更新日時をバージョンとして返す。
*/
function nines_asset_version(string $path): string
{
$file = get_template_directory() . '/' . ltrim($path, '/');
return file_exists($file) ? (string) filemtime($file) : wp_get_theme()->get('Version');
}
/**
* SVGを安全な場所から読み込む。
*/
function nines_inline_svg(string $path, string $class = ''): string
{
$file = get_template_directory() . '/' . ltrim($path, '/');
if (!is_readable($file) || pathinfo($file, PATHINFO_EXTENSION) !== 'svg') {
return '';
}
$svg = file_get_contents($file);
if ($svg === false) {
return '';
}
if ($class !== '') {
$svg = preg_replace('/<svg\b(?![^>]*class=)/', '<svg class="' . esc_attr($class) . '"', $svg, 1);
}
return $svg;
}
/**
* アイキャッチがなければデフォルト画像を返す。
*/
function nines_featured_image_url(?int $post_id = null, string $size = 'large'): string
{
$post_id = $post_id ?: get_the_ID();
$url = get_the_post_thumbnail_url($post_id, $size);
return esc_url($url ?: get_template_directory_uri() . '/images/any_eyecatch.png');
}
/**
* ページ種別に応じたbody classを追加する。
*/
add_filter('body_class', function (array $classes): array {
if (is_singular('post')) {
$classes[] = 'is-blog-detail';
}
if (is_page()) {
$classes[] = 'is-page-' . sanitize_html_class((string) get_post_field('post_name'));
}
return array_values(array_unique($classes));
});
/**
* OGPに使う説明文を返す。
*/
function nines_meta_description(?int $post_id = null, int $length = 120): string
{
$post_id = $post_id ?: get_the_ID();
$description = has_excerpt($post_id)
? get_the_excerpt($post_id)
: wp_strip_all_tags(get_post_field('post_content', $post_id));
return esc_attr(wp_html_excerpt(trim($description), $length, '...'));
}
/**
* パンくず用の配列を返す。
*/
function nines_breadcrumb_items(): array
{
$items = [
['label' => 'HOME', 'url' => home_url('/')],
];
if (is_singular('post')) {
$items[] = ['label' => 'BLOG', 'url' => home_url('/blog/')];
$items[] = ['label' => get_the_title(), 'url' => get_permalink()];
} elseif (is_page()) {
$items[] = ['label' => get_the_title(), 'url' => get_permalink()];
}
return $items;
}
/**
* titleタグや見出しで使うページタイトルを返す。
*/
function nines_page_title(): string
{
if (is_home() || is_front_page()) {
return get_bloginfo('name');
}
if (is_archive()) {
return get_the_archive_title();
}
if (is_search()) {
return '検索結果: ' . get_search_query();
}
return get_the_title() ?: get_bloginfo('name');
}
/**
* メニューを配列で取得する。
*/
function nines_menu_items(string $location): array
{
$locations = get_nav_menu_locations();
if (!isset($locations[$location])) {
return [];
}
$items = wp_get_nav_menu_items($locations[$location]);
return is_array($items) ? $items : [];
}
/**
* 投稿カード表示に必要な情報をまとめて返す。
*/
function nines_post_card_data(?WP_Post $post = null): array
{
$post = $post ?: get_post();
if (!$post instanceof WP_Post) {
return [];
}
return [
'id' => $post->ID,
'title' => get_the_title($post),
'url' => get_permalink($post),
'date' => get_the_date('Y.m.d', $post),
'image' => nines_featured_image_url($post->ID, 'medium_large'),
'excerpt' => get_the_excerpt($post),
];
}便利関数1: nines_asset
テーマ内の画像、CSS、JavaScriptのURLを返す関数です。テンプレート内でget_template_directory_uri()を何度も書かずに済みます。
<?php echo nines_asset('images/logo.svg'); ?>便利関数2: nines_asset_version
CSSやJavaScriptの更新日時をバージョンに使う関数です。ファイルを更新したのに古いCSSが残るキャッシュ問題を減らせます。
wp_enqueue_style('theme-style', nines_asset('style.css'), [], nines_asset_version('style.css'));便利関数3: nines_inline_svg
SVGをインラインで読み込む関数です。アイコンの色をCSSで変えたい場合や、ロゴをcurrentColorで扱いたい場合に便利です。外部入力のパスをそのまま渡さず、テーマ内の固定ファイルに使うのが安全です。
<?php echo nines_inline_svg('images/svg2/nines_logo.svg', 'site-logo'); ?>便利関数4: nines_featured_image_url
アイキャッチがある場合はそのURLを返し、ない場合はデフォルト画像を返します。記事カードの画像抜けを防げます。
<img src="<?php echo nines_featured_image_url(); ?>" alt="<?php the_title_attribute(); ?>">便利関数5: body_classの追加
ページ種別に応じたclassをbodyへ追加します。CSSでページごとの調整をするとき、テンプレート側に余計な分岐を書かずに済みます。
便利関数6: nines_meta_description
OGPやmeta descriptionで使う説明文を返します。抜粋があれば抜粋を使い、なければ本文から短く切り出します。
<meta name="description" content="<?php echo nines_meta_description(); ?>">便利関数7: nines_breadcrumb_items
パンくずに必要なラベルとURLを配列で返します。HTMLの出し方はテンプレート側で自由に変えられるので、デザイン変更にも対応しやすいです。
便利関数8: nines_page_title
トップ、アーカイブ、検索、固定ページ、投稿ページで表示するタイトルをまとめます。見出しやtitleタグの出し分けに使えます。
<h1><?php echo esc_html(nines_page_title()); ?></h1>便利関数9: nines_menu_items
登録済みメニューを配列で取得します。メニューのHTMLを細かく制御したい場合に使いやすい関数です。
便利関数10: nines_post_card_data
投稿カードで使うタイトル、URL、日付、画像、抜粋をまとめて返します。ループ内のテンプレートがかなり読みやすくなります。
<?php foreach ($query->posts as $post) : ?>
<?php $card = nines_post_card_data($post); ?>
<a href="<?php echo esc_url($card['url']); ?>">
<img src="<?php echo esc_url($card['image']); ?>" alt="">
<span><?php echo esc_html($card['date']); ?></span>
<strong><?php echo esc_html($card['title']); ?></strong>
</a>
<?php endforeach; ?>おすすめディレクトリ構成
theme-root/
├── functions.php
├── inc/
│ ├── helpers.php
│ ├── setup.php
│ └── enqueue.php
├── template-parts/
│ ├── card-post.php
│ └── breadcrumb.php
├── css/
├── js/
└── images/命名規則
- テーマ固有の関数には接頭辞を付ける。例: nines_asset()
- HTMLを返す関数とデータを返す関数を混ぜすぎない
- esc_url、esc_html、esc_attrなど、出力場所に合わせてエスケープする
- 関数が増えたらfunctions.phpからinc/helpers.phpへ分ける
- WordPress標準関数でできることは、独自実装しすぎない
FAQ
functions.phpに全部書いてもいいですか?
小さなテーマなら問題ありません。ただ、関数が増えてきたらinc/helpers.php、inc/enqueue.phpのように分ける方が管理しやすいです。
SVG読み込み関数は安全ですか?
テーマ内に置いた信頼できるSVGだけを読み込む前提なら扱いやすいです。管理画面からアップロードされたSVGや外部URLをそのまま読み込む使い方は避けてください。
便利関数を作りすぎるデメリットはありますか?
あります。WordPress標準関数を薄く包むだけの関数が増えすぎると、逆に読みづらくなります。テンプレートの重複を減らせるもの、変更に強くなるものだけを残すのがおすすめです。
内部リンク案
まとめ
WordPressオリジナルテーマでは、最初に便利関数を整えておくと、テンプレートの見通しがかなり良くなります。特にasset、SVG、アイキャッチ、OGP、パンくず、投稿カードは使う頻度が高いので、早めに用意しておく価値があります。