2025年08月07日[木曜日]

テンプレートとfunctions.phpの整理によるコード保守性の向上

  • 2025/08/07
  • BASICS
  • WordPressの基礎
  • 0comments
  • 28views
  • 約23分で読めます
  • 39

前回の記事でカフェメニューシステムが完成しましたが、開発を進めるうちに各テンプレートファイルに同じようなコードが重複して記述され、functions.phpも肥大化してきました。

今回は、コードの整理整頓により保守性を向上させる技術について学習します。これにより、機能追加や修正が格段に行いやすくなる開発環境を整えましょう。

今回の目標

  • 重複コードの問題認識:なぜコードの重複が問題となるのか
  • get_template_partによる共通部分の外部化:重複コードを解消する仕組み
  • functions.phpの機能別ファイル分割:メンテナンスしやすい構造作り
  • require_onceによる読み込み管理:分割したファイルの適切な統合

なぜコードの整理が必要になるのか

WordPressテーマ開発が進むと、以下のような2つの問題が発生します。

問題1:テンプレートファイルでのコード重複

複数のテンプレートで同じメニュー表示コードを記述することになり、以下の問題が生じます。

  • 修正時の手間:一箇所の変更で複数ファイルを修正する必要
  • 修正漏れのリスク:どこかのファイルの修正を忘れて表示が不整合になる
  • コードの保守困難:同じコードが散らばっているため管理が大変

問題2:functions.phpの肥大化

様々な機能を追加していくと、functions.phpに以下のコードが混在します。

  • カスタム投稿タイプの登録
  • テーマサポート機能の設定
  • CSS・JSファイルの読み込み
  • カスタマイズ機能

これにより、どこに何が書かれているかが分からなくなり、メンテナンスが困難になります。

WordPressには、これらの問題を解決するコードを整理整頓する仕組みが用意されています。

解決方法の概要

今回学習する2つの解決アプローチ。

  1. get_template_partによる共通部分の外部化:重複コードを1つのファイルにまとめる
  2. functions.phpの機能別ファイル分割:大きくなったfunctions.phpを機能別に分割する

これらにより、コードの保守性が大幅に向上します。

問題1の解決:テンプレートの重複コードを整理

現在のコード重複の確認

前回までの作業で、以下のメニュー表示コードが複数箇所に重複して記述されています。

page-cafe-menu.php(カフェメニュー一覧)とtaxonomy-tax-menu.php(カテゴリー別一覧)の両方に、ほぼ同じコードが存在しています。

<?php
    // Smart Custom Fieldsの繰り返しフィールドから価格を取得
    $prices = SCF::get('price_group');
    $first_price = '';
    if (!empty($prices) && !empty($prices[0]['price'])) {
      $first_price = $prices[0]['price'] . '円〜';
    }

?>
  <li class="menu-item">
    <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
  <?php if (has_post_thumbnail()) : ?>
    <div class="menu-thumbnail">
      <a href="<?php the_permalink(); ?>">
        <?php the_post_thumbnail('medium'); ?>
      </a>
    </div>
  <?php endif; ?>

    <?php if (has_excerpt()) : ?>
      <p class="menu-excerpt"><?php the_excerpt(); ?></p>
    <?php endif; ?>
    <?php if ($first_price) : ?>
      <p class="menu-price"><?php echo $first_price; ?></p>
    <?php endif; ?>
  </li>
PHP

この重複により、デザインを変更したい場合は2箇所を修正する必要があり、修正漏れのリスクがあります。

get_template_partによる共通部分の外部化

WordPressにはget_template_partという関数があり、共通のコードを外部ファイル化して読み込むことができます。

共通テンプレートファイルの作成

テーマフォルダ内にpartsフォルダを作成し、共通のメニュー項目表示用ファイルmenu-item.phpを作成します。

menu-item.php
<?php
    // Smart Custom Fieldsの繰り返しフィールドから価格を取得
    $prices = SCF::get('price_group');
    $first_price = '';
    if (!empty($prices) && !empty($prices[0]['price'])) {
      $first_price = $prices[0]['price'] . '円〜';
    }

?>
  <li class="menu-item">
    <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
  <?php if (has_post_thumbnail()) : ?>
    <div class="menu-thumbnail">
      <a href="<?php the_permalink(); ?>">
        <?php the_post_thumbnail('medium'); ?>
      </a>
    </div>
  <?php endif; ?>

    <?php if (has_excerpt()) : ?>
      <p class="menu-excerpt"><?php the_excerpt(); ?></p>
    <?php endif; ?>
    <?php if ($first_price) : ?>
      <p class="menu-price"><?php echo $first_price; ?></p>
    <?php endif; ?>
  </li>
PHP

テンプレートファイルでの読み込み

page-cafe-menu.phpmenu-item.php読み込むため、以下のように修正します。

page-cafe-menu.php
<?php get_header(); ?>
<?php the_content(); ?>

<?php
  // メニューカテゴリーを term_order 順で取得
  $menu_categories = get_terms(
    array(
      'taxonomy' => 'tax-menu',
      'hide_empty' => true,
      'orderby' => 'term_order',
      'order' => 'ASC'
    )
  );

  foreach ($menu_categories as $category) :
?>
  <h2>
    <a href="<?php echo get_term_link($category); ?>">
      <?php echo $category->name; ?>
    </a>
  </h2>

<?php
  $args = [
    'post_type' => 'menu_post',
    'post_status' => 'publish',
    'orderby' => 'menu_order',
    'order' => 'ASC',
    'posts_per_page' => -1,
    'tax_query' => array(
      array(
        'taxonomy' => 'tax-menu',
        'field' => 'term_id',
        'terms' => $category->term_id,
      ),
    ),
  ];

  // 現在のカテゴリーに属するメニューを取得
  $menu_query = new WP_Query($args);
?>
  <ul class="menu-list">
  <?php
    while ($menu_query->have_posts()) : 
      $menu_query->the_post();
      get_template_part('parts/menu-item');
    endwhile;
  ?>
  </ul>
<?php
  wp_reset_postdata();
  endforeach;
?>

<p>※このページは page-cafe-menu.php テンプレートで表示されています</p>
<?php get_footer();?>
PHP

同じようにtaxonomy-tax-menu.phpも修正します。

taxonomy-tax-menu.php
<?php get_header();?>
<?php the_content(); ?>

<?php
  $target = get_queried_object();

  // そのカテゴリーに属する投稿を取得
  $args = [
    'post_type' => 'menu_post',
    'post_status' => 'publish',
    'orderby' => 'menu_order',
    'order' => 'asc',
    'tax_query' => [
      [
        'taxonomy' => $target->taxonomy,
        'field' => 'term_id',
        'terms' => $target->term_id,
      ]
    ]
  ];

  // 現在のカテゴリーに属するメニューを取得
  $menu_query = new WP_Query($args);
?>
  <ul class="menu-list">
  <?php
    while ($menu_query->have_posts()) : 
      $menu_query->the_post();
      get_template_part('parts/menu-item');
    endwhile;
  ?>
</ul>

<p>※このページは taxonomy-tax-menu.php テンプレートで表示されています</p>
<?php get_footer();?>
PHP

get_template_partの基本的な使い方

phpget_template_part('parts/menu-item');
PHP
  • 第1引数:読み込むファイルのパス(拡張子.phpは不要)
  • 動作:指定されたファイルを読み込んで実行
  • スコープ:読み込み元の変数やWordPressのループ情報を共有

これにより、メニュー項目の表示デザインを変更したい場合はparts/menu-item.phpのみを修正すれば、すべての一覧ページに反映されます。

問題2の解決:functions.phpの機能別ファイル分割

現在のfunctions.phpには、以下のような様々な機能が混在しています。

  • テーマサポート機能:メニュー、titleタグ、アイキャッチ画像の有効化
  • CSS・JSファイル読み込み:スタイルシートの読み込み処理
  • カスタムタイトル設定:ページタイトルのカスタマイズ
  • カスタム投稿タイプ:カフェメニューの登録
  • カスタムタクソノミー:店舗、メニューカテゴリーの登録

これらすべてが1つのファイルに記述されているため、特定の機能を修正したい場合でも、長大なfunctions.phpの中から該当箇所を探す必要があります。

分割用フォルダの作成

テーマフォルダ内にfuncフォルダを作成し、機能別のファイルを配置します。今回はフォルダ名をfuncとしましたが任意のフォルダ名で大丈夫です。

テーマフォルダ
├── functions.php
├── func
│   ├── theme-func-support.php      # テーマサポート関連
│   ├── theme-func-enqueue.php      # CSS・JSファイル読み込み
│   ├── theme-func-post-types.php   # カスタム投稿タイプ関連
│   └── theme-func-custom.php       # その他のカスタマイズ
└── parts
    └── menu-item.php

ファイル名のプレフィックスについて:ファイル名の重複を避けるため「theme-func-」というプレフィックスを付けています。

機能別ファイルの作成

theme-func-support.php

theme-func-support.php
<?php
// テーマサポート機能の設定

// 外観→メニューの有効化
add_theme_support('menus');

// titleタグの有効化
add_theme_support('title-tag');

// アイキャッチ画像サポートを有効化
add_theme_support('post-thumbnails');
PHP

theme-func-enqueue.php

theme-func-enqueue.php
<?php
// スタイルシートとスクリプトの読み込み

add_action('wp_enqueue_scripts', 'load_theme_style');
function load_theme_style() {
  wp_enqueue_style(
    'theme-main-style',
    get_stylesheet_directory_uri() . '/main.css',
    array(),
    filemtime(get_stylesheet_directory() . '/main.css'),
  );
  wp_enqueue_style(
    'theme-sub-style',
    get_stylesheet_directory_uri() . '/sub.css',
    array('theme-main-style'),
    filemtime(get_stylesheet_directory() . '/sub.css'),
  );
}
PHP

theme-func-post-types.php

theme-func-post-types.php
<?php
// カスタム投稿タイプとタクソノミーの登録

// 店舗タクソノミー(通常投稿用)
add_action('init', function() {
  register_taxonomy(
    'tax-store',
    'post',
    array(
      'labels' => array(
        'name'              => '店舗',
        'singular_name'     => '店舗',
        'search_items'      => '店舗を検索',
        'all_items'         => 'すべての店舗',
        'parent_item'       => '親店舗',
        'parent_item_colon' => '親店舗:',
        'edit_item'         => '店舗の編集',
        'update_item'       => '店舗を更新',
        'add_new_item'      => '新しい店舗を追加',
        'new_item_name'     => '新しい店舗名',
        'menu_name'         => '店舗',
      ),
      'hierarchical' => true,
      'public' => true,
      'show_in_rest' => true,
      'show_admin_column' => true,
      'show_in_quick_edit' => true,
      'show_in_nav_menus' => true,
      'query_var' => 'store',
      'rewrite' => array(
          'slug' => 'store',
          'with_front' => true,
      ),
    )
  );
});

// カフェメニューのカスタム投稿タイプ
add_action('init', function() {
  register_post_type(
    'menu_post',
    array(
      'labels' => array(
        'name' => __('カフェメニュー'),
        'all_items' => __('カフェメニュー一覧'),
        'add_new' => __('カフェメニューを追加する'),
        'add_new_item' => __('カフェメニューの追加'),
        'edit_item' => __('カフェメニューの編集'),
        'singular_name' => __('カフェメニュータイプ'),
        'new_item' => __('新しいカフェメニュー'),
        'view_item' => __('カフェメニューを見る'),
        'search_items' => __('カフェメニューを探す'),
        'not_found' => __('カフェメニューはありません'),
        'not_found_in_trash' => __('ゴミ箱にカフェメニューはありません'),
      ),
      'public' => true,
      'hierarchical' => false,
      'supports' => array(
        'title',
        'editor',
        'page-attributes',
        'thumbnail',
        'excerpt',
        'custom-fields'
      ),
      'rewrite' => array(
        'slug' => 'menu',
        'with_front' => false,
      ),
      'menu_icon' => 'dashicons-food',
      'show_in_rest' => true,
    )
  );
});

// メニューカテゴリーのカスタムタクソノミー
add_action('init', function() {
  register_taxonomy(
    'tax-menu',
    'menu_post',
    array(
      'labels' => array(
        'name'              => 'メニューカテゴリー',
        'singular_name'     => 'メニューカテゴリー',
        'search_items'      => 'メニューカテゴリーを検索',
        'all_items'         => 'すべてのメニューカテゴリー',
        'parent_item'       => '親メニューカテゴリー',
        'parent_item_colon' => '親メニューカテゴリー:',
        'edit_item'         => 'メニューカテゴリーの編集',
        'update_item'       => 'メニューカテゴリーを更新',
        'add_new_item'      => '新しいメニューカテゴリーを追加',
        'new_item_name'     => '新しいメニューカテゴリー名',
        'menu_name'         => 'メニューカテゴリー',
      ),
      'hierarchical' => true,
      'public' => true,
      'show_in_rest' => true,
      'show_admin_column' => true,
      'show_in_quick_edit' => true,
      'show_in_nav_menus' => true,
      'query_var' => 'menu-category',
      'rewrite' => array(
        'slug' => 'menu-category',
        'with_front' => false,
      ),
    )
  );
});
PHP

theme-func-custom.php

theme-func-custom.php
<?php
// その他のカスタマイズ機能

// カスタムタイトルタグの設定
function custom_document_title($title) {
  $custom_title = '';

  if (is_front_page()) {
    // サイトタイトルを取得
    $custom_title = get_bloginfo('name');
  } else {
    // 現在表示中のページタイトルを取得
    $custom_title = get_the_title();

    // 現在ページの親ページIDを取得
    $parent_id = wp_get_post_parent_id(get_the_ID());
    // 親ページが存在する場合(IDが0以外)、親ページのタイトルを追加
    if ($parent_id) {
      // 親ページのタイトルを取得
      $custom_title = $custom_title . '|';
      $custom_title = $custom_title . get_the_title($parent_id);
    }

    // サイトタイトルを取得
    $custom_title = $custom_title . '|';
    $custom_title = $custom_title . get_bloginfo('name');
  }

  return $custom_title;
}
add_filter('pre_get_document_title', 'custom_document_title');
PHP

require_onceによる読み込み管理

functions.phpを以下のように整理します。

functions.php
<?php
// テーマの基本設定とファイル読み込み

// 機能別ファイルの読み込み
require_once get_stylesheet_directory() . '/func/theme-func-support.php';
require_once get_stylesheet_directory() . '/func/theme-func-enqueue.php';
require_once get_stylesheet_directory() . '/func/theme-func-post-types.php';
require_once get_stylesheet_directory() . '/func/theme-func-custom.php';

// その他のfunctions.php独自の処理があればここに記述
PHP

require_onceの基本的な使い方

require_once get_stylesheet_directory() . '/func/theme-func-support.php';
PHP
  • require_once:ファイルを1回だけ読み込む(重複読み込みを防ぐ)
  • get_stylesheet_directory():現在のテーマフォルダの絶対パスを取得
  • 動作:指定されたファイルの内容を実行

これにより、functions.phpがスッキリと整理され、各機能の編集時は対応するファイルのみを修正すれば済みます。

整理による効果

今回の整理により、以下の効果が得られます。

コード修正の効率化

  • メニュー表示の変更parts/menu-item.phpのみ修正
  • カスタム投稿タイプの変更func/theme-func-post-types.phpのみ修正
  • CSS読み込みの変更func/theme-func-enqueue.phpのみ修正
  • テーマサポートの追加func/theme-func-support.phpのみ修正

バグの発生リスク軽減

  • 修正漏れの防止:共通部分は1箇所のみの修正
  • 影響範囲の明確化:どのファイルがどの機能を担当するか明確

拡張性の向上

  • 新機能の追加:新しいfuncファイルを作成してrequire_onceで読み込むだけ
  • 機能の無効化require_once行をコメントアウトするだけで機能を停止
  • コードの把握:どこに何が書かれているかが明確で、修正箇所を素早く特定

まとめ

今回の学習で、WordPressテーマ開発におけるコード保守性の向上技術を身につけました。

  • get_template_partによる共通テンプレートの外部化
  • 機能別ファイル分割による論理的なコード整理
  • require_onceによる適切なファイル読み込み管理

これらの技術により、開発効率が向上し、メンテナンスしやすいWordPressテーマの基盤が整いました。

学習が進むにつれて、さらに多くの機能が追加されることになりますが、今回学んだ整理手法を活用することで、常に保守性の高いコードを維持できます。

成果物

この記事で作成した成果物は、以下のページでまとめて確認することができます。

成果物をまとめて確認する

この記事の評価をお願いします

評価をすると「既読」となり、まだ読んでいない記事を区別できます。

この投稿をシェアする

コメントを残す

CAPTCHA



カスタム投稿の総仕上げ - 商品情報の充実でメニューシステムを完成させよう

カスタム投稿の総仕上げ - 商品情報の充実でメニューシステムを完成させよう  BASICS

カスタム投稿の基本機能に加えて、抜粋・アイキャッチ・カスタムフィールドを追加する方法を学習します。これらの機能を有効化する手順、管理画面での入力方法、テンプレートでの表示方法を理解することで、より実用的なコンテンツ管理が可能になります。

  • 2025/08/07
  • 0comments
  • 45views

STAY CONNECTED

wp-ch Admin

現役のフリーランスエンジニアがWordPressによるWebサイト構築を基礎から実践テクニックまで徹底解説します。

たくさんの方がフォローしてくれています。あなたもぜひ、情報を受け取ってください。

STORY|ストーリー

WordPressを効率よく確実に学ぶためには、学習の順序が大切です。知識が自然に積み上がるよう、学習ステップに沿って記事を順番に並べています。

学習ストーリー第39話まで掲載中

全ストーリーを見る