wordpressの必要最低限のサンプル
説明の多い、親切なサイトがたくさんありますが、コピペできるような超シンプルなテンプレートのひな形を作りました。各テンプレートファイルの必要最低限の記載です。
とりあえず貼り付けての改造用にどうぞ。
style.css
必須のテンプレートの1つで、テーマ名の記載が必要です。
/*
Theme Name: Minimal Theme
Theme URI:
Author: Your Name
Author URI:
Description: A minimal WordPress theme
Version: 1.0
License: GNU General Public License v2 or later
*/
/* style.css */
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
}
.container {
width: 80%;
margin: 0 auto;
}
header.php
※タイトルタグをheadに書かず、functions.phpに下記を入れるとwordpressが書き出してくれます。
add_theme_support( 'title-tag' );
/* header.php */
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<header>
<div class="container">
<h1><a href="<?php echo home_url(); ?>"><?php bloginfo('name'); ?></a></h1>
<nav>
<?php wp_nav_menu(array('theme_location' => 'primary-menu')); ?>
</nav>
</div>
</header>
index.php
/* index.php */
<?php get_header(); ?>
<main class="container">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<article>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
</article>
<?php endwhile; endif; ?>
</main>
<?php get_footer(); ?>
front-page.php
/* front-page.php */
<?php get_header(); ?>
<main class="container">
<section class="hero">
<h2><?php bloginfo('description'); ?></h2>
</section>
<section class="latest-posts">
<h2>最新の記事</h2>
<?php
$args = array(
'post_type' => 'post',
'posts_per_page' => 3
);
$latest_posts = new WP_Query($args);
if ($latest_posts->have_posts()) : while ($latest_posts->have_posts()) : $latest_posts->the_post();
?>
<article>
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<?php the_post_thumbnail('medium'); ?>
</div>
<?php endif; ?>
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<?php the_excerpt(); ?>
</article>
<?php
endwhile;
wp_reset_postdata();
endif;
?>
</section>
</main>
<?php get_footer(); ?>
page.php
/* page.php */
<?php get_header(); ?>
<main class="container">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<article class="page-content">
<h1><?php the_title(); ?></h1>
<?php if (has_post_thumbnail()) : ?>
<div class="page-thumbnail">
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
<div class="page-text">
<?php the_content(); ?>
</div>
</article>
<?php endwhile; endif; ?>
</main>
<?php get_footer(); ?>
single.php
/* single.php */
<?php get_header(); ?>
<main class="container">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<article class="single-post">
<header class="post-header">
<h1><?php the_title(); ?></h1>
<div class="post-meta">
<time><?php the_time('Y年n月j日'); ?></time>
<span class="post-author"><?php the_author(); ?></span>
<span class="post-categories"><?php the_category(', '); ?></span>
</div>
</header>
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
<div class="post-content">
<?php the_content(); ?>
</div>
<footer class="post-footer">
<?php the_tags('<div class="post-tags">タグ: ', ', ', '</div>'); ?>
<?php comments_template(); ?>
</footer>
</article>
<?php endwhile; endif; ?>
</main>
<?php get_footer(); ?>
archive.php
/* archive.php */
<?php get_header(); ?>
<main class="container">
<header class="archive-header">
<h1>
<?php
if (is_category()) {
single_cat_title('カテゴリー: ');
} elseif (is_tag()) {
single_tag_title('タグ: ');
} elseif (is_author()) {
echo '投稿者: ' . get_the_author();
} elseif (is_date()) {
if (is_year()) {
echo get_the_date('Y年').'の記事';
} elseif (is_month()) {
echo get_the_date('Y年n月').'の記事';
}
} else {
echo 'アーカイブ';
}
?>
</h1>
</header>
<?php if (have_posts()) : ?>
<div class="archive-posts">
<?php while (have_posts()) : the_post(); ?>
<article class="archive-post">
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<?php the_post_thumbnail('medium'); ?>
</div>
<?php endif; ?>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<div class="post-meta">
<time><?php the_time('Y年n月j日'); ?></time>
</div>
<?php the_excerpt(); ?>
</article>
<?php endwhile; ?>
<div class="pagination">
<?php echo paginate_links(); ?>
</div>
</div>
<?php else : ?>
<p>記事が見つかりませんでした。</p>
<?php endif; ?>
</main>
<?php get_footer(); ?>
footer.php
/* footer.php */
<footer>
<div class="container">
<p>© <?php echo date('Y'); ?> <?php bloginfo('name'); ?></p>
</div>
</footer>
<?php wp_footer(); ?>
</body>
</html>
###404.php
/* 404.php */
<?php get_header(); ?>
<main class="container">
<div class="error-404">
<h1>404 - ページが見つかりません</h1>
<p>お探しのページは存在しないか、移動した可能性があります。</p>
<div class="search-form">
<h2>サイト内検索</h2>
<?php get_search_form(); ?>
</div>
<div class="recent-posts">
<h2>最近の投稿</h2>
<ul>
<?php
wp_get_archives(array(
'type' => 'postbypost',
'limit' => 5
));
?>
</ul>
</div>
</div>
</main>
<?php get_footer(); ?>
searchform.php
/* searchform.php */
<form role="search" method="get" class="search-form" action="<?php echo home_url('/'); ?>">
<label>
<span class="screen-reader-text">検索:</span>
<input type="search" class="search-field" placeholder="検索..." value="<?php echo get_search_query(); ?>" name="s" />
</label>
<button type="submit" class="search-submit">検索</button>
</form>
search.php
/* search.php */
<?php get_header(); ?>
<main class="container">
<header class="page-header">
<h1>
<?php
printf(
'検索結果: %s',
'<span>' . get_search_query() . '</span>'
);
?>
</h1>
</header>
<?php if (have_posts()) : ?>
<div class="search-results">
<?php while (have_posts()) : the_post(); ?>
<article class="search-result">
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<div class="entry-meta">
<span class="post-type"><?php echo get_post_type(); ?></span>
<time><?php the_time('Y年n月j日'); ?></time>
</div>
<?php the_excerpt(); ?>
</article>
<?php endwhile; ?>
<?php echo paginate_links(); ?>
</div>
<?php else : ?>
<div class="no-results">
<p>検索条件に一致する記事は見つかりませんでした。</p>
<?php get_search_form(); ?>
</div>
<?php endif; ?>
</main>
<?php get_footer(); ?>
sidebar.php
/* sidebar.php */
<aside class="widget-area">
<?php if (is_active_sidebar('sidebar-1')) : ?>
<?php dynamic_sidebar('sidebar-1'); ?>
<?php else : ?>
<section class="widget">
<h2 class="widget-title">カテゴリー</h2>
<ul>
<?php wp_list_categories('title_li='); ?>
</ul>
</section>
<section class="widget">
<h2 class="widget-title">アーカイブ</h2>
<ul>
<?php wp_get_archives('type=monthly'); ?>
</ul>
</section>
<?php endif; ?>
</aside>
###comments.php
/* comments.php */
<?php
if (post_password_required()) {
return;
}
?>
<div id="comments" class="comments-area">
<?php if (have_comments()) : ?>
<h2 class="comments-title">
<?php
printf(
_n(
'コメント(%1$s)',
'コメント(%1$s)',
get_comments_number()
),
number_format_i18n(get_comments_number())
);
?>
</h2>
<ol class="comment-list">
<?php
wp_list_comments(array(
'style' => 'ol',
'short_ping' => true,
'avatar_size' => 60,
));
?>
</ol>
<?php if (get_comment_pages_count() > 1 && get_option('page_comments')) : ?>
<nav class="comment-navigation">
<div class="nav-previous"><?php previous_comments_link('前のコメント'); ?></div>
<div class="nav-next"><?php next_comments_link('次のコメント'); ?></div>
</nav>
<?php endif; ?>
<?php endif; ?>
<?php if (!comments_open() && get_comments_number() && post_type_supports(get_post_type(), 'comments')) : ?>
<p class="no-comments">コメントは締め切られました。</p>
<?php endif; ?>
<?php comment_form(); ?>
</div>
template-parts/content.php
/* template-parts/content.php */
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php if (is_singular()) : ?>
<h1 class="entry-title"><?php the_title(); ?></h1>
<?php else : ?>
<h2 class="entry-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<?php endif; ?>
<?php if ('post' === get_post_type()) : ?>
<div class="entry-meta">
<span class="posted-on">
<?php the_time('Y年n月j日'); ?>
</span>
<span class="byline">
<?php the_author_posts_link(); ?>
</span>
</div>
<?php endif; ?>
</header>
<?php if (has_post_thumbnail() && !is_singular()) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
</div>
<?php endif; ?>
<div class="entry-content">
<?php
if (is_singular()) {
the_content();
} else {
the_excerpt();
echo '<a href="' . esc_url(get_permalink()) . '" class="more-link">続きを読む</a>';
}
?>
</div>
</article>
functions.php
/* functions.php */
<?php
//スイッチオフになっている機能をオンにする
function minimal_theme_setup() {
register_nav_menus(array('primary-menu' => 'Primary Menu')); //管理画面でメニューの作成・編集が可能になる
add_theme_support('automatic-feed-links'); //RSSフィードのリンクを自動的に出力
add_theme_support('post-thumbnails'); //投稿やページでアイキャッチ画像を使用可能に
add_theme_support('title-tag'); //ページタイトルの自動出力をサポート
}
add_action('after_setup_theme', 'minimal_theme_setup');
//jsとCSS読み込み
function my_script_init() {
wp_enqueue_style("font-awesome", "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css", array(), "5.8.2", "all");
wp_enqueue_style("my", get_template_directory_uri() . "/css/style.css", array(), filemtime(get_theme_file_path('css/style.css')), "all");
wp_enqueue_script("my", get_template_directory_uri() . "/js/script.js", array("jquery"), filemtime(get_theme_file_path('js/script.js')), true);
}
add_action("wp_enqueue_scripts", "my_script_init");
カスタムフィールド
よくありそうなサンプル集
<?php
/**
* WordPress ACF Pro テンプレートサンプル(シンプル版)
* post_type: post を使用
*/
// ===========================================
// 1. functions.php - 基本設定のみ
// ===========================================
// テーマサポート
function theme_setup() {
add_theme_support('post-thumbnails');
add_theme_support('title-tag');
}
add_action('after_setup_theme', 'theme_setup');
// カテゴリー自動作成(テーマ有効化時)
function create_default_categories() {
$categories = ['ビジネス', 'テクノロジー', 'ライフスタイル', 'エンターテイメント', 'スポーツ'];
foreach ($categories as $cat_name) {
if (!term_exists($cat_name, 'category')) {
wp_insert_term($cat_name, 'category');
}
}
}
add_action('after_switch_theme', 'create_default_categories');
// ===========================================
// 2. index.php - メインページ
// ===========================================
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body>
<div class="container">
<header>
<h1><?php bloginfo('name'); ?></h1>
<p><?php bloginfo('description'); ?></p>
</header>
<!-- カテゴリーナビゲーション -->
<nav>
<a href="<?php echo home_url(); ?>">すべて</a>
<?php
$categories = get_categories();
foreach ($categories as $category) {
echo '<a href="' . get_category_link($category->term_id) . '">' . $category->name . '</a> ';
}
?>
</nav>
<!-- 投稿一覧 -->
<main>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php
$priority = get_field('priority');
$subtitle = get_field('subtitle');
?>
<article>
<?php if (has_post_thumbnail()) : ?>
<div>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
</div>
<?php endif; ?>
<div>
<h2>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<?php if ($subtitle) : ?>
<p><em><?php echo $subtitle; ?></em></p>
<?php endif; ?>
<div>
<?php echo get_the_date(); ?> |
<?php the_category(', '); ?>
<?php if ($priority && $priority !== 'normal') : ?>
| <strong>【<?php echo $priority === 'important' ? '重要' : '緊急'; ?>】</strong>
<?php endif; ?>
</div>
<div>
<?php the_excerpt(); ?>
</div>
<?php
$custom_tags = get_field('tags_custom');
if ($custom_tags) :
$tags_array = explode(',', $custom_tags);
?>
<div>
<strong>タグ: </strong>
<?php foreach ($tags_array as $tag) : ?>
<span><?php echo trim($tag); ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</article>
<hr>
<?php endwhile; endif; ?>
</main>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php
// ===========================================
// 3. single.php - 個別投稿ページ
// ===========================================
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body>
<div class="container">
<a href="<?php echo home_url(); ?>">← トップページに戻る</a>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php
$priority = get_field('priority');
$subtitle = get_field('subtitle');
$featured_alt = get_field('featured_image_alt');
$custom_tags = get_field('tags_custom');
$related_links = get_field('related_links');
?>
<article>
<header>
<h1>
<?php the_title(); ?>
<?php if ($priority && $priority !== 'normal') : ?>
<span>【<?php echo $priority === 'important' ? '重要' : '緊急'; ?>】</span>
<?php endif; ?>
</h1>
<?php if ($subtitle) : ?>
<p><em><?php echo $subtitle; ?></em></p>
<?php endif; ?>
<div>
投稿日: <?php echo get_the_date(); ?> |
カテゴリー: <?php the_category(', '); ?> |
投稿者: <?php the_author(); ?>
</div>
</header>
<?php if (has_post_thumbnail()) : ?>
<div>
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
<div>
<?php the_content(); ?>
</div>
<?php if ($featured_alt) : ?>
<div>
<h3>関連画像</h3>
<img src="<?php echo $featured_alt['url']; ?>" alt="<?php echo $featured_alt['alt']; ?>">
</div>
<?php endif; ?>
<?php if ($custom_tags) : ?>
<div>
<strong>タグ: </strong>
<?php
$tags_array = explode(',', $custom_tags);
foreach ($tags_array as $tag) :
?>
<span><?php echo trim($tag); ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($related_links) : ?>
<div>
<h3>関連リンク</h3>
<ul>
<?php foreach ($related_links as $link) : ?>
<li>
<a href="<?php echo $link['link_url']; ?>" target="_blank" rel="noopener">
<?php echo $link['link_title']; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
</article>
<?php endwhile; endif; ?>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php
// ===========================================
// 4. category.php - カテゴリー別一覧ページ
// ===========================================
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php single_cat_title(); ?> | <?php bloginfo('name'); ?></title>
<?php wp_head(); ?>
</head>
<body>
<div class="container">
<a href="<?php echo home_url(); ?>">← トップページに戻る</a>
<header>
<h1><?php single_cat_title(); ?></h1>
<p><?php echo category_description(); ?></p>
<p><strong><?php echo $wp_query->found_posts; ?></strong> 件の記事があります</p>
</header>
<main>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php
$priority = get_field('priority');
$subtitle = get_field('subtitle');
?>
<article>
<?php if (has_post_thumbnail()) : ?>
<div>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
</div>
<?php endif; ?>
<div>
<h2>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
<?php if ($priority && $priority !== 'normal') : ?>
<span>【<?php echo $priority === 'important' ? '重要' : '緊急'; ?>】</span>
<?php endif; ?>
</a>
</h2>
<?php if ($subtitle) : ?>
<p><em><?php echo $subtitle; ?></em></p>
<?php endif; ?>
<div>
<?php echo get_the_date(); ?> | <?php the_author(); ?>
</div>
<div>
<?php the_excerpt(); ?>
</div>
</div>
</article>
<hr>
<?php endwhile; else : ?>
<div>
<h2>まだ投稿がありません</h2>
<p>このカテゴリーにはまだ記事が投稿されていません。</p>
</div>
<?php endif; ?>
</main>
<!-- ページネーション -->
<div>
<?php previous_posts_link('← 前のページ'); ?>
<?php next_posts_link('次のページ →'); ?>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php
// ===========================================
// 5. style.css - テーマ情報
// ===========================================
/*
Theme Name: ACF Sample Theme
Description: ACF Proを使ったシンプルなサンプルテーマ
Version: 1.0
Author: Your Name
*/
?>
<?php
// ===========================================
// ACF Pro プラグイン設定内容
// ===========================================
/*
【フィールドグループ作成手順】
1. ACF Pro管理画面で「フィールドグループ」→「新規追加」
2. フィールドグループ名: 「投稿詳細情報」
3. 以下のフィールドを追加:
■ フィールド1: サブタイトル
- フィールドラベル: サブタイトル
- フィールド名: subtitle
- フィールドタイプ: テキスト
- 説明: タイトルの補足説明
■ フィールド2: アイキャッチ画像(追加)
- フィールドラベル: アイキャッチ画像(追加)
- フィールド名: featured_image_alt
- フィールドタイプ: 画像
- 説明: メイン画像とは別の補助画像
- 戻り値: 画像配列
■ フィールド3: 記事の重要度
- フィールドラベル: 記事の重要度
- フィールド名: priority
- フィールドタイプ: セレクトボックス
- 選択肢:
normal : 通常
important : 重要
urgent : 緊急
- デフォルト値: normal
■ フィールド4: カスタムタグ
- フィールドラベル: カスタムタグ
- フィールド名: tags_custom
- フィールドタイプ: テキスト
- 説明: カンマ区切りで入力
■ フィールド5: 関連リンク
- フィールドラベル: 関連リンク
- フィールド名: related_links
- フィールドタイプ: リピーター
- 最小行数: 0
- 最大行数: 5
- レイアウト: テーブル
サブフィールド1:
- フィールドラベル: リンクタイトル
- フィールド名: link_title
- フィールドタイプ: テキスト
サブフィールド2:
- フィールドラベル: URL
- フィールド名: link_url
- フィールドタイプ: URL
4. 位置ルール設定:
- 投稿タイプ が次と等しい post
5. 設定:
- 位置: コンテンツエディタの下
- スタイル: デフォルト
- ラベルの配置: 上
*/
?>
カスタム投稿タイプサンプル2
<?php
/**
* WordPress Food カスタム投稿テンプレート(別パターン)
* カスタム投稿タイプ: food
* カスタムタクソノミー: cuisine_type
*/
// ===========================================
// 1. functions.php - カスタム投稿タイプとタクソノミー登録
// ===========================================
// カスタム投稿タイプ「food」の登録
function register_food_post_type() {
register_post_type('food', array(
'label' => 'レシピ',
'public' => true,
'has_archive' => true,
'supports' => array('title', 'editor', 'thumbnail', 'author'),
'menu_icon' => 'dashicons-carrot',
'rewrite' => array('slug' => 'recipe'),
'labels' => array(
'name' => 'レシピ',
'singular_name' => 'レシピ',
'add_new' => '新規追加',
'add_new_item' => '新しいレシピを追加',
'edit_item' => 'レシピを編集',
'new_item' => '新しいレシピ',
'view_item' => 'レシピを表示',
'search_items' => 'レシピを検索',
'not_found' => 'レシピが見つかりません',
),
));
}
add_action('init', 'register_food_post_type');
// カスタムタクソノミー「cuisine_type」の登録
function register_cuisine_taxonomy() {
register_taxonomy('cuisine_type', 'food', array(
'label' => '料理ジャンル',
'public' => true,
'hierarchical' => true,
'show_ui' => true,
'show_admin_column' => true,
'rewrite' => array('slug' => 'cuisine'),
'labels' => array(
'name' => '料理ジャンル',
'singular_name' => '料理ジャンル',
'add_new_item' => '新しいジャンルを追加',
'edit_item' => 'ジャンルを編集',
),
));
}
add_action('init', 'register_cuisine_taxonomy');
// デフォルトタクソノミーターム作成
function create_default_cuisine_terms() {
$terms = array(
'japanese' => '和食',
'western' => '洋食',
'chinese' => '中華',
'italian' => 'イタリアン',
'korean' => '韓国料理'
);
foreach ($terms as $slug => $name) {
if (!term_exists($name, 'cuisine_type')) {
wp_insert_term($name, 'cuisine_type', array('slug' => $slug));
}
}
}
add_action('after_switch_theme', 'create_default_cuisine_terms');
// ===========================================
// 2. archive-food.php - レシピ一覧ページ
// ===========================================
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>レシピ一覧 | <?php bloginfo('name'); ?></title>
<?php wp_head(); ?>
</head>
<body>
<div class="container">
<header>
<h1>今日のおすすめレシピ</h1>
<p>各ジャンルから最新のレシピをご紹介</p>
<a href="<?php echo home_url(); ?>">← ホームに戻る</a>
</header>
<?php
// 投稿があるタクソノミータームのみ取得
$terms = get_terms(array(
'taxonomy' => 'cuisine_type',
'hide_empty' => true,
'orderby' => 'slug',
'order' => 'ASC'
));
?>
<?php if (!empty($terms) && !is_wp_error($terms)) : ?>
<!-- ページ内ナビゲーション -->
<nav class="quick-nav">
<h2>ジャンル別メニュー</h2>
<ul>
<?php foreach ($terms as $term) : ?>
<li>
<a href="#<?php echo esc_attr($term->slug); ?>">
<?php echo esc_html($term->name); ?>
<span>(<?php echo $term->count; ?>)</span>
</a>
</li>
<?php endforeach; ?>
</ul>
</nav>
<!-- 各ジャンルのセクション -->
<main class="recipes-container">
<?php foreach ($terms as $term) : ?>
<section id="<?php echo esc_attr($term->slug); ?>" class="cuisine-section">
<header class="section-header">
<h2><?php echo esc_html($term->name); ?></h2>
<?php if ($term->description) : ?>
<p><?php echo esc_html($term->description); ?></p>
<?php endif; ?>
<a href="<?php echo get_term_link($term); ?>" class="view-all">
すべての<?php echo esc_html($term->name); ?>を見る →
</a>
</header>
<?php
// 各ジャンルの最新レシピ1件を取得
$recipe_query = new WP_Query(array(
'post_type' => 'food',
'post_status' => 'publish',
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'DESC',
'tax_query' => array(
array(
'taxonomy' => 'cuisine_type',
'field' => 'term_id',
'terms' => $term->term_id,
),
),
));
?>
<?php if ($recipe_query->have_posts()) : ?>
<?php while ($recipe_query->have_posts()) : $recipe_query->the_post(); ?>
<article class="featured-recipe">
<div class="recipe-image">
<?php if (has_post_thumbnail()) : ?>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('large'); ?>
</a>
<?php else : ?>
<div class="no-image">画像なし</div>
<?php endif; ?>
</div>
<div class="recipe-content">
<h3>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</h3>
<div class="recipe-meta">
<span class="date">投稿: <?php echo get_the_date('Y.m.d'); ?></span>
<span class="author">by <?php the_author(); ?></span>
</div>
<div class="recipe-excerpt">
<?php
if (has_excerpt()) {
the_excerpt();
} else {
echo wp_trim_words(get_the_content(), 30, '...');
}
?>
</div>
<?php
// ジャンル別カスタムフィールド表示
echo '<div class="recipe-details">';
switch ($term->slug) {
case 'japanese':
$cooking_method = get_field('cooking_method');
$dashi_type = get_field('dashi_type');
$regional_style = get_field('regional_style');
if ($cooking_method) echo '<span class="detail-item"><strong>調理法:</strong> ' . esc_html($cooking_method) . '</span>';
if ($dashi_type) echo '<span class="detail-item"><strong>だし:</strong> ' . esc_html($dashi_type) . '</span>';
if ($regional_style) echo '<span class="detail-item"><strong>郷土:</strong> ' . esc_html($regional_style) . '</span>';
break;
case 'western':
$course_type = get_field('course_type');
$origin_country = get_field('origin_country');
$wine_pairing = get_field('wine_pairing');
if ($course_type) echo '<span class="detail-item"><strong>コース:</strong> ' . esc_html($course_type) . '</span>';
if ($origin_country) echo '<span class="detail-item"><strong>発祥:</strong> ' . esc_html($origin_country) . '</span>';
if ($wine_pairing) echo '<span class="detail-item"><strong>ワイン:</strong> ' . esc_html($wine_pairing) . '</span>';
break;
case 'chinese':
$cooking_style = get_field('cooking_style');
$spice_level = get_field('spice_level');
$region_china = get_field('region_china');
if ($cooking_style) echo '<span class="detail-item"><strong>調理法:</strong> ' . esc_html($cooking_style) . '</span>';
if ($spice_level) echo '<span class="detail-item"><strong>辛さ:</strong> ' . esc_html($spice_level) . '</span>';
if ($region_china) echo '<span class="detail-item"><strong>地方:</strong> ' . esc_html($region_china) . '</span>';
break;
case 'italian':
$pasta_type = get_field('pasta_type');
$cheese_type = get_field('cheese_type');
$region_italy = get_field('region_italy');
if ($pasta_type) echo '<span class="detail-item"><strong>パスタ:</strong> ' . esc_html($pasta_type) . '</span>';
if ($cheese_type) echo '<span class="detail-item"><strong>チーズ:</strong> ' . esc_html($cheese_type) . '</span>';
if ($region_italy) echo '<span class="detail-item"><strong>地方:</strong> ' . esc_html($region_italy) . '</span>';
break;
case 'korean':
$fermentation = get_field('fermentation');
$gochujang_level = get_field('gochujang_level');
$meal_type = get_field('meal_type');
if ($fermentation) echo '<span class="detail-item"><strong>発酵:</strong> ' . ($fermentation ? 'あり' : 'なし') . '</span>';
if ($gochujang_level) echo '<span class="detail-item"><strong>コチュジャン:</strong> ' . esc_html($gochujang_level) . '</span>';
if ($meal_type) echo '<span class="detail-item"><strong>食事タイプ:</strong> ' . esc_html($meal_type) . '</span>';
break;
}
// 共通フィールド
$prep_time = get_field('prep_time');
$difficulty = get_field('difficulty');
$servings = get_field('servings');
if ($prep_time) echo '<span class="detail-item"><strong>調理時間:</strong> ' . esc_html($prep_time) . '分</span>';
if ($difficulty) echo '<span class="detail-item"><strong>難易度:</strong> ' . esc_html($difficulty) . '</span>';
if ($servings) echo '<span class="detail-item"><strong>人数:</strong> ' . esc_html($servings) . '人分</span>';
echo '</div>';
?>
<a href="<?php the_permalink(); ?>" class="read-more">
レシピを見る →
</a>
</div>
</article>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>
<?php else : ?>
<div class="no-recipes">
<p>まだ<?php echo esc_html($term->name); ?>のレシピがありません。</p>
</div>
<?php endif; ?>
</section>
<?php endforeach; ?>
</main>
<?php else : ?>
<div class="no-content">
<h2>レシピがまだありません</h2>
<p>最初のレシピを投稿してみましょう!</p>
</div>
<?php endif; ?>
<!-- トップに戻るリンク -->
<div class="back-to-top">
<a href="#page-top">↑ ページトップへ</a>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php
// ===========================================
// 3. single-food.php - 個別レシピページ
// ===========================================
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body>
<div class="container">
<nav class="breadcrumb">
<a href="<?php echo home_url(); ?>">ホーム</a> >
<a href="<?php echo get_post_type_archive_link('food'); ?>">レシピ一覧</a> >
<span><?php the_title(); ?></span>
</nav>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<article class="recipe-detail">
<header class="recipe-header">
<h1><?php the_title(); ?></h1>
<div class="recipe-meta">
<div class="meta-item">
<strong>投稿日:</strong> <?php echo get_the_date('Y年m月d日'); ?>
</div>
<div class="meta-item">
<strong>投稿者:</strong> <?php the_author(); ?>
</div>
<div class="meta-item">
<strong>ジャンル:</strong>
<?php
$terms = get_the_terms(get_the_ID(), 'cuisine_type');
if ($terms && !is_wp_error($terms)) {
$term_links = array();
foreach ($terms as $term) {
$term_links[] = '<a href="' . get_term_link($term) . '">' . esc_html($term->name) . '</a>';
}
echo implode(', ', $term_links);
}
?>
</div>
</div>
</header>
<?php if (has_post_thumbnail()) : ?>
<div class="recipe-image">
<?php the_post_thumbnail('full'); ?>
</div>
<?php endif; ?>
<div class="recipe-summary">
<?php the_content(); ?>
</div>
<?php
// 現在の投稿のジャンルを取得
$current_terms = get_the_terms(get_the_ID(), 'cuisine_type');
if ($current_terms && !is_wp_error($current_terms)) {
foreach ($current_terms as $current_term) {
echo '<section class="cuisine-details">';
echo '<h2>' . esc_html($current_term->name) . ' レシピ詳細</h2>';
// ジャンル別の詳細フィールド表示
switch ($current_term->slug) {
case 'japanese':
$cooking_method = get_field('cooking_method');
$dashi_type = get_field('dashi_type');
$regional_style = get_field('regional_style');
$ingredients_japanese = get_field('ingredients_japanese');
$seasonality = get_field('seasonality');
echo '<div class="detail-grid">';
if ($cooking_method) echo '<div class="detail-item"><strong>調理法:</strong> ' . esc_html($cooking_method) . '</div>';
if ($dashi_type) echo '<div class="detail-item"><strong>だしの種類:</strong> ' . esc_html($dashi_type) . '</div>';
if ($regional_style) echo '<div class="detail-item"><strong>郷土料理:</strong> ' . esc_html($regional_style) . '</div>';
if ($seasonality) echo '<div class="detail-item"><strong>旬の季節:</strong> ' . esc_html($seasonality) . '</div>';
echo '</div>';
if ($ingredients_japanese) {
echo '<h3>材料</h3><ul>';
foreach ($ingredients_japanese as $ingredient) {
echo '<li>' . esc_html($ingredient['ingredient_name']) . ' - ' . esc_html($ingredient['amount']) . '</li>';
}
echo '</ul>';
}
break;
case 'western':
$course_type = get_field('course_type');
$origin_country = get_field('origin_country');
$wine_pairing = get_field('wine_pairing');
$ingredients_western = get_field('ingredients_western');
$cooking_tips = get_field('cooking_tips');
echo '<div class="detail-grid">';
if ($course_type) echo '<div class="detail-item"><strong>コース:</strong> ' . esc_html($course_type) . '</div>';
if ($origin_country) echo '<div class="detail-item"><strong>発祥国:</strong> ' . esc_html($origin_country) . '</div>';
if ($wine_pairing) echo '<div class="detail-item"><strong>ワインペアリング:</strong> ' . esc_html($wine_pairing) . '</div>';
echo '</div>';
if ($ingredients_western) {
echo '<h3>材料</h3><ul>';
foreach ($ingredients_western as $ingredient) {
echo '<li>' . esc_html($ingredient['ingredient_name']) . ' - ' . esc_html($ingredient['quantity']) . '</li>';
}
echo '</ul>';
}
if ($cooking_tips) echo '<div class="cooking-tips"><h3>調理のコツ</h3><p>' . esc_html($cooking_tips) . '</p></div>';
break;
case 'chinese':
$cooking_style = get_field('cooking_style');
$spice_level = get_field('spice_level');
$region_china = get_field('region_china');
$seasonings_chinese = get_field('seasonings_chinese');
echo '<div class="detail-grid">';
if ($cooking_style) echo '<div class="detail-item"><strong>調理法:</strong> ' . esc_html($cooking_style) . '</div>';
if ($spice_level) echo '<div class="detail-item"><strong>辛さレベル:</strong> ' . esc_html($spice_level) . '</div>';
if ($region_china) echo '<div class="detail-item"><strong>中国地方:</strong> ' . esc_html($region_china) . '</div>';
echo '</div>';
if ($seasonings_chinese) {
echo '<h3>調味料</h3><ul>';
foreach ($seasonings_chinese as $seasoning) {
echo '<li>' . esc_html($seasoning['seasoning_name']) . ' - ' . esc_html($seasoning['usage']) . '</li>';
}
echo '</ul>';
}
break;
case 'italian':
$pasta_type = get_field('pasta_type');
$cheese_type = get_field('cheese_type');
$region_italy = get_field('region_italy');
$olive_oil_type = get_field('olive_oil_type');
echo '<div class="detail-grid">';
if ($pasta_type) echo '<div class="detail-item"><strong>パスタの種類:</strong> ' . esc_html($pasta_type) . '</div>';
if ($cheese_type) echo '<div class="detail-item"><strong>チーズ:</strong> ' . esc_html($cheese_type) . '</div>';
if ($region_italy) echo '<div class="detail-item"><strong>イタリア地方:</strong> ' . esc_html($region_italy) . '</div>';
if ($olive_oil_type) echo '<div class="detail-item"><strong>オリーブオイル:</strong> ' . esc_html($olive_oil_type) . '</div>';
echo '</div>';
break;
case 'korean':
$fermentation = get_field('fermentation');
$gochujang_level = get_field('gochujang_level');
$meal_type = get_field('meal_type');
$kimchi_pairing = get_field('kimchi_pairing');
echo '<div class="detail-grid">';
if ($fermentation !== null) echo '<div class="detail-item"><strong>発酵食品:</strong> ' . ($fermentation ? 'あり' : 'なし') . '</div>';
if ($gochujang_level) echo '<div class="detail-item"><strong>コチュジャンレベル:</strong> ' . esc_html($gochujang_level) . '</div>';
if ($meal_type) echo '<div class="detail-item"><strong>食事タイプ:</strong> ' . esc_html($meal_type) . '</div>';
if ($kimchi_pairing) echo '<div class="detail-item"><strong>キムチとの相性:</strong> ' . esc_html($kimchi_pairing) . '</div>';
echo '</div>';
break;
}
echo '</section>';
}
}
// 共通の詳細情報
$prep_time = get_field('prep_time');
$difficulty = get_field('difficulty');
$servings = get_field('servings');
$cooking_steps = get_field('cooking_steps');
if ($prep_time || $difficulty || $servings) {
echo '<section class="common-details">';
echo '<h2>基本情報</h2>';
echo '<div class="detail-grid">';
if ($prep_time) echo '<div class="detail-item"><strong>調理時間:</strong> ' . esc_html($prep_time) . '分</div>';
if ($difficulty) echo '<div class="detail-item"><strong>難易度:</strong> ' . esc_html($difficulty) . '</div>';
if ($servings) echo '<div class="detail-item"><strong>人数:</strong> ' . esc_html($servings) . '人分</div>';
echo '</div>';
echo '</section>';
}
if ($cooking_steps) {
echo '<section class="cooking-steps">';
echo '<h2>作り方</h2>';
echo '<ol>';
foreach ($cooking_steps as $index => $step) {
echo '<li><div class="step-content">' . esc_html($step['step_description']) . '</div></li>';
}
echo '</ol>';
echo '</section>';
}
?>
</article>
<?php endwhile; endif; ?>
<div class="navigation-links">
<a href="<?php echo get_post_type_archive_link('food'); ?>">← レシピ一覧に戻る</a>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php
// ===========================================
// 4. taxonomy-cuisine_type.php - ジャンル別一覧ページ
// ===========================================
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php single_term_title(); ?> のレシピ | <?php bloginfo('name'); ?></title>
<?php wp_head(); ?>
</head>
<body>
<div class="container">
<nav class="breadcrumb">
<a href="<?php echo home_url(); ?>">ホーム</a> >
<a href="<?php echo get_post_type_archive_link('food'); ?>">レシピ一覧</a> >
<span><?php single_term_title(); ?></span>
</nav>
<header class="taxonomy-header">
<h1><?php single_term_title(); ?> のレシピ</h1>
<?php if (term_description()) : ?>
<div class="taxonomy-description">
<?php echo term_description(); ?>
</div>
<?php endif; ?>
<p class="recipe-count">
<strong><?php echo $wp_query->found_posts; ?></strong> 件のレシピがあります
</p>
</header>
<main class="recipes-list">
<?php if (have_posts()) : ?>
<div class="recipes-grid">
<?php while (have_posts()) : the_post(); ?>
<article class="recipe-card">
<?php if (has_post_thumbnail()) : ?>
<div class="card-image">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
</div>
<?php endif; ?>
<div class="card-content">
<h2 class="card-title">
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</h2>
<div class="card-meta">
<span class="date"><?php echo get_the_date('Y.m.d'); ?></span>
<span class="author">by <?php the_author(); ?></span>
</div>
<div class="card-excerpt">
<?php
if (has_excerpt()) {
the_excerpt();
} else {
echo wp_trim_words(get_the_content(), 20, '...');
}
?>
</div>
<?php
// 現在のタクソノミーターム情報を取得
$current_term = get_queried_object();
// ジャンル別の簡易情報表示
echo '<div class="card-details">';
switch ($current_term->slug) {
case 'japanese':
$cooking_method = get_field('cooking_method');
$dashi_type = get_field('dashi_type');
if ($cooking_method) echo '<span class="detail-tag">' . esc_html($cooking_method) . '</span>';
if ($dashi_type) echo '<span class="detail-tag">' . esc_html($dashi_type) . '</span>';
break;
case 'western':
$course_type = get_field('course_type');
$origin_country = get_field('origin_country');
if ($course_type) echo '<span class="detail-tag">' . esc_html($course_type) . '</span>';
if ($origin_country) echo '<span class="detail-tag">' . esc_html($origin_country) . '</span>';
break;
case 'chinese':
$cooking_style = get_field('cooking_style');
$spice_level = get_field('spice_level');
if ($cooking_style) echo '<span class="detail-tag">' . esc_html($cooking_style) . '</span>';
if ($spice_level) echo '<span class="detail-tag">辛さ: ' . esc_html($spice_level) . '</span>';
break;
case 'italian':
$pasta_type = get_field('pasta_type');
$region_italy = get_field('region_italy');
if ($pasta_type) echo '<span class="detail-tag">' . esc_html($pasta_type) . '</span>';
if ($region_italy) echo '<span class="detail-tag">' . esc_html($region_italy) . '</span>';
break;
case 'korean':
$meal_type = get_field('meal_type');
$gochujang_level = get_field('gochujang_level');
if ($meal_type) echo '<span class="detail-tag">' . esc_html($meal_type) . '</span>';
if ($gochujang_level) echo '<span class="detail-tag">' . esc_html($gochujang_level) . '</span>';
break;
}
// 共通フィールド
$prep_time = get_field('prep_time');
$difficulty = get_field('difficulty');
if ($prep_time) echo '<span class="detail-tag">' . esc_html($prep_time) . '分</span>';
if ($difficulty) echo '<span class="detail-tag">' . esc_html($difficulty) . '</span>';
echo '</div>';
?>
<a href="<?php the_permalink(); ?>" class="read-more">
レシピを見る →
</a>
</div>
</article>
<?php endwhile; ?>
</div>
<?php else : ?>
<div class="no-recipes">
<h2>レシピがまだありません</h2>
<p>この<?php single_term_title(); ?>ジャンルにはまだレシピが投稿されていません。</p>
</div>
<?php endif; ?>
</main>
<!-- ページネーション -->
<nav class="pagination">
<?php
echo paginate_links(array(
'prev_text' => '← 前のページ',
'next_text' => '次のページ →',
));
?>
</nav>
<div class="navigation-links">
<a href="<?php echo get_post_type_archive_link('food'); ?>">← レシピ一覧に戻る</a>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
<?php
// ===========================================
// ACF Pro プラグイン設定内容
// ===========================================
/*
【フィールドグループ設定】
■ 共通フィールドグループ
フィールドグループ名: レシピ基本情報
位置ルール: 投稿タイプ が次と等しい food
フィールド:
1. 調理時間 (prep_time) - 数値
2. 難易度 (difficulty) - セレクト(簡単/普通/難しい/上級者向け)
3. 人数 (servings) - 数値
4. 作り方 (cooking_steps) - リピーター
- 手順説明 (step_description) - テキストエリア
■ 和食専用フィールドグループ
フィールドグループ名: 和食詳細情報
位置ルール:
- 投稿タイプ が次と等しい food
- かつ タクソノミー が次と等しい 和食 (cuisine_type)
フィールド:
1. 調理法 (cooking_method) - セレクト(煮る/焼く/蒸す/炒める/揚げる/生/その他)
2. だしの種類 (dashi_type) - セレクト(昆布/かつお/煮干し/あご/複合/なし)
3. 郷土料理 (regional_style) - テキスト
4. 旬の季節 (seasonality) - セレクト(春/夏/秋/冬/通年)
5. 材料 (ingredients_japanese) - リピーター
- 材料名 (ingredient_name) - テキスト
- 分量 (amount) - テキスト
■ 洋食専用フィールドグループ
フィールドグループ名: 洋食詳細情報
位置ルール:
- 投稿タイプ が次と等しい food
- かつ タクソノミー が次と等しい 洋食 (cuisine_type)
フィールド:
1. コースタイプ (course_type) - セレクト(前菜/スープ/メイン/デザート/フルコース)
2. 発祥国 (origin_country) - テキスト
3. ワインペアリング (wine_pairing) - テキスト
4. 調理のコツ (cooking_tips) - テキストエリア
5. 材料 (ingredients_western) - リピーター
- 材料名 (ingredient_name) - テキスト
- 分量 (quantity) - テキスト
■ 中華専用フィールドグループ
フィールドグループ名: 中華詳細情報
位置ルール:
- 投稿タイプ が次と等しい food
- かつ タクソノミー が次と等しい 中華 (cuisine_type)
フィールド:
1. 調理法 (cooking_style) - セレクト(炒/煮/蒸/揚/焼/涼拌)
2. 辛さレベル (spice_level) - セレクト(なし/微辛/中辛/激辛)
3. 中国地方 (region_china) - セレクト(北京/上海/四川/広東/湖南/その他)
4. 調味料 (seasonings_chinese) - リピーター
- 調味料名 (seasoning_name) - テキスト
- 使用法 (usage) - テキスト
■ イタリアン専用フィールドグループ
フィールドグループ名: イタリアン詳細情報
位置ルール:
- 投稿タイプ が次と等しい food
- かつ タクソノミー が次と等しい イタリアン (cuisine_type)
フィールド:
1. パスタの種類 (pasta_type) - セレクト(ロングパスタ/ショートパスタ/リゾット/ニョッキ/パスタなし)
2. チーズの種類 (cheese_type) - テキスト
3. イタリア地方 (region_italy) - セレクト(北部/中部/南部/シチリア/サルデーニャ)
4. オリーブオイル (olive_oil_type) - セレクト(エクストラバージン/ピュア/使用なし)
■ 韓国料理専用フィールドグループ
フィールドグループ名: 韓国料理詳細情報
位置ルール:
- 投稿タイプ が次と等しい food
- かつ タクソノミー が次と等しい 韓国料理 (cuisine_type)
フィールド:
1. 発酵食品 (fermentation) - 真偽値
2. コチュジャンレベル (gochujang_level) - セレクト(なし/少し/普通/たっぷり)
3. 食事タイプ (meal_type) - セレクト(ご飯/麺/鍋/おかず/おつまみ/デザート)
4. キムチとの相性 (kimchi_pairing) - セレクト(とても良い/良い/普通/合わない)
【設定手順】
1. ACF Pro管理画面で各フィールドグループを作成
2. 位置ルールで「投稿タイプ = food」かつ「タクソノミー = 該当ジャンル」を設定
3. 各ジャンルに応じた専用フィールドを追加
4. 共通フィールドグループは全てのfood投稿に適用
【タクソノミーターム作成】
WordPress管理画面 > レシピ > 料理ジャンル で以下を作成:
- 和食 (slug: japanese)
- 洋食 (slug: western)
- 中華 (slug: chinese)
- イタリアン (slug: italian)
- 韓国料理 (slug: korean)
*/
?>
説明が欲しい方へ
# WordPress Food テンプレート 詳細解説
## 全体概要
このテンプレートは、レシピサイト用のWordPressカスタム投稿タイプシステムです。各料理ジャンルに特化したカスタムフィールドを持ち、ジャンル別に最適化された情報表示を行います。
## 1. functions.php の詳細解説
### カスタム投稿タイプ「food」登録
```php
function register_food_post_type() {
register_post_type('food', array(
-
register_food_post_typeという関数を定義 - WordPressに新しい投稿タイプを登録する
'label' => 'レシピ',
- 管理画面での表示名を「レシピ」に設定
'public' => true,
- 一般公開する投稿タイプとして設定(フロントエンドで表示可能)
'has_archive' => true,
- アーカイブページ(一覧ページ)を作成可能にする
'supports' => array('title', 'editor', 'thumbnail', 'author'),
- 投稿で使用可能な機能を指定
- title: タイトル、editor: 本文エディタ、thumbnail: アイキャッチ画像、author: 投稿者
'menu_icon' => 'dashicons-carrot',
- 管理画面メニューのアイコンを人参マークに設定
'rewrite' => array('slug' => 'recipe'),
- URLのスラッグを「recipe」に設定(例: /recipe/post-name/)
カスタムタクソノミー「cuisine_type」登録
function register_cuisine_taxonomy() {
register_taxonomy('cuisine_type', 'food', array(
-
cuisine_typeというタクソノミーをfood投稿タイプに関連付けて登録
'hierarchical' => true,
- 階層構造を持つタクソノミーとして設定(カテゴリーのような親子関係が可能)
'show_admin_column' => true,
- 管理画面の投稿一覧にタクソノミーの列を表示
デフォルトターム作成
function create_default_cuisine_terms() {
$terms = array(
'japanese' => '和食',
'western' => '洋食',
'chinese' => '中華',
'italian' => 'イタリアン',
'korean' => '韓国料理'
);
- 作成するタクソノミータームを配列で定義
- キー: スラッグ、値: 表示名
if (!term_exists($name, 'cuisine_type')) {
wp_insert_term($name, 'cuisine_type', array('slug' => $slug));
}
-
term_exists()でタームが既に存在するかチェック - 存在しない場合のみ
wp_insert_term()で新規作成
2. archive-food.php の詳細解説
タクソノミータームの取得
$terms = get_terms(array(
'taxonomy' => 'cuisine_type',
'hide_empty' => true,
'orderby' => 'slug',
'order' => 'ASC'
));
-
get_terms()で料理ジャンルの一覧を取得 -
hide_empty => true: 投稿が1件もないタームは除外 -
orderby => 'slug': スラッグ順で並び替え -
order => 'ASC': 昇順で並び替え
ページ内ナビゲーション生成
<?php foreach ($terms as $term) : ?>
<li>
<a href="#<?php echo esc_attr($term->slug); ?>">
- 各タームのスラッグを
id属性として使用してページ内リンクを作成 -
esc_attr()でHTMLエスケープしてセキュリティ対策
<span>(<?php echo $term->count; ?>)</span>
-
$term->countでそのタームに属する投稿数を表示
各ジャンルの最新投稿取得
$recipe_query = new WP_Query(array(
'post_type' => 'food',
'post_status' => 'publish',
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'DESC',
-
WP_Queryでカスタムクエリを作成 -
post_type => 'food': foodタイプの投稿のみ -
post_status => 'publish': 公開済みの投稿のみ -
posts_per_page => 1: 1件のみ取得 -
orderby => 'date', order => 'DESC': 投稿日時の新しい順
'tax_query' => array(
array(
'taxonomy' => 'cuisine_type',
'field' => 'term_id',
'terms' => $term->term_id,
),
),
-
tax_queryでタクソノミーによる絞り込み - 現在のタームに属する投稿のみを取得
ジャンル別カスタムフィールド表示
switch ($term->slug) {
case 'japanese':
$cooking_method = get_field('cooking_method');
$dashi_type = get_field('dashi_type');
$regional_style = get_field('regional_style');
-
switch文で現在のタームのスラッグに応じて処理を分岐 -
get_field()でACFのカスタムフィールド値を取得
if ($cooking_method) echo '<span class="detail-item"><strong>調理法:</strong> ' . esc_html($cooking_method) . '</span>';
- フィールドに値が入っている場合のみ表示
-
esc_html()でHTMLエスケープしてセキュリティ対策
投稿データのリセット
<?php wp_reset_postdata(); ?>
- カスタムクエリ後に必須の処理
- グローバルな投稿データを元の状態に戻す
3. single-food.php の詳細解説
パンくずナビの作成
<nav class="breadcrumb">
<a href="<?php echo home_url(); ?>">ホーム</a> >
<a href="<?php echo get_post_type_archive_link('food'); ?>">レシピ一覧</a> >
<span><?php the_title(); ?></span>
</nav>
-
get_post_type_archive_link('food')でfood投稿タイプのアーカイブページURLを取得 - 現在のページ位置を視覚的に分かりやすく表示
投稿に紐づくタクソノミーターム取得
$terms = get_the_terms(get_the_ID(), 'cuisine_type');
if ($terms && !is_wp_error($terms)) {
-
get_the_terms()で現在の投稿に関連付けられたタームを取得 -
!is_wp_error()でエラーがないかチェック
foreach ($terms as $term) {
$term_links[] = '<a href="' . get_term_link($term) . '">' . esc_html($term->name) . '</a>';
}
echo implode(', ', $term_links);
- 各タームをリンク付きで表示
-
get_term_link()でタームのアーカイブページURLを取得 -
implode()で配列を文字列に結合(カンマ区切り)
ジャンル別詳細情報の表示
if ($current_terms && !is_wp_error($current_terms)) {
foreach ($current_terms as $current_term) {
switch ($current_term->slug) {
- 投稿に関連付けられた各タームに対してループ処理
- タームのスラッグに応じて異なる情報を表示
リピーターフィールドの処理
if ($ingredients_japanese) {
echo '<h3>材料</h3><ul>';
foreach ($ingredients_japanese as $ingredient) {
echo '<li>' . esc_html($ingredient['ingredient_name']) . ' - ' . esc_html($ingredient['amount']) . '</li>';
}
echo '</ul>';
}
- ACFのリピーターフィールドは配列として返される
-
foreachで各行をループ処理 -
$ingredient['field_name']でサブフィールドの値を取得
共通フィールドの表示
$prep_time = get_field('prep_time');
$difficulty = get_field('difficulty');
$servings = get_field('servings');
$cooking_steps = get_field('cooking_steps');
- 全ジャンル共通のフィールドを取得
- ジャンル固有の情報とは別セクションで表示
4. taxonomy-cuisine_type.php の詳細解説
現在のタクソノミー情報取得
$current_term = get_queried_object();
-
get_queried_object()で現在表示中のタクソノミーターム情報を取得 - アーカイブページで現在のタームを特定するために使用
ページネーション
echo paginate_links(array(
'prev_text' => '← 前のページ',
'next_text' => '次のページ →',
));
-
paginate_links()でページネーション(ページ送り)を生成 - 前後のページへのリンクテキストをカスタマイズ
投稿数の表示
<p class="recipe-count">
<strong><?php echo $wp_query->found_posts; ?></strong> 件のレシピがあります
</p>
-
$wp_query->found_postsで現在のクエリに該当する投稿の総数を取得 - ページング考慮済みの総件数
ACF設定のポイント
位置ルールの条件分岐
位置ルール:
- 投稿タイプ が次と等しい food
- かつ タクソノミー が次と等しい 和食 (cuisine_type)
- ACFの位置ルールで「かつ」条件を使用
- 特定のタクソノミーが選択された時のみフィールドを表示
フィールドタイプの選択指針
- テキスト: 短い文字列(材料名、地域名など)
- テキストエリア: 長い文章(説明、コツなど)
- セレクト: 決まった選択肢から選ぶ(難易度、調理法など)
- 数値: 数字のみ(時間、人数など)
- 真偽値: はい/いいえの選択(発酵食品かどうかなど)
- リピーター: 可変長のリスト(材料、手順など)
セキュリティ対策
-
esc_html(): HTMLタグを無効化 -
esc_attr(): HTML属性値を安全に出力 -
esc_url(): URLを安全に出力
パフォーマンス考慮
-
wp_reset_postdata(): カスタムクエリ後の必須処理 -
hide_empty => true: 空のタームを除外してクエリ効率化 - 条件分岐で不要な処理をスキップ
拡張可能な部分
- 追加ジャンル: 新しい料理ジャンルとそれ専用のフィールド
- 検索機能: カスタムフィールドでの絞り込み検索
- お気に入り機能: ユーザーごとのレシピ保存
- 評価システム: 星評価やレビュー機能
- 栄養情報: カロリー計算や栄養素表示