WordPress:テンプレート階層がややこしすぎる

WordPress:テンプレート階層がややこしすぎる

テーマをゼロから作ってみる(6)です。無料であれ有料であれ公開されているものを使わずにゼロからテーマを作ってみようというシリーズです。完成形の目標は次のサイトです。

01Android の Chrome が固まる件について

実はこの記事、この記事を表示すると Android の Chrome だけ(私だけかも…)固まるという症状が出ていましたので、しばらく次のお断りを入れていました。

根本的な原因はまだつかめていませんが、その症状が出る原因となっているプラグインが判明しましたので再度公開することにしました。そのプラグインは Highlighting Code Block です。もちろんプラグインに原因があるという意味ではなく、このプラグインを無効化しますとその症状は出ないということです。引き続き原因究明を図ります。

02これまでの経緯と single.php

これまでの経緯はこちらです。

現在のところ、個別投稿ページがほぼ出来上がっています。CSS の細かい調整や装飾は後回しにしていますので基本的な構造だけです。

左が個別投稿ページのページトップ部分です。サイトタイトルの下に、アイキャッチ画像、パンくずリスト、記事タイトル、投稿日、本文と続きます。右が記事の末尾、ページャー、サイドバー部分です。

ここまでテンプレートファイルは index.php で作ってきていますが、次にフロントページ(ホームページ)を作るにあたり、個別投稿ページのテンプレートを single.php の別ファイルにしました。以下が現状の single.php です。詳細はこれまでの経緯 1〜5 をご覧ください。

(Android 上の Chrome 限定の注意)
コードブロックをタップしますと数秒固まる場合があります。スクロール等他の操作に支障はありません。Chrome のバグとの報告が上がっています。詳細は「AndroidのChromeだけ固まる(止まる)ってどういうこと?!」をご覧ください。

<!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 id="pagetop" class="site-container">
	<header class="site-header">
		<p class="site-title"><a href="<?php echo esc_url(home_url('/')); ?>" title="<?php bloginfo('name'); ?>"><?php bloginfo('name'); ?></a></p>
		<p class="site-description"><?php bloginfo('description'); ?></p>
	</header>
	<nav class="primary-nav">
		<?php wp_nav_menu( array( 'theme_location' => 'primary-nav' ) ); ?>
	</nav>
	<?php if(has_post_thumbnail()) : ?>
	<div class="featured-image-wrap">
		<div class="featured-image" style="background-image:url('<?php the_post_thumbnail_url(); ?>')"></div>
	</div>
	<?php endif; ?>
	<div class="main-sidebar-container">
		<main class="main-container">
    	<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
			<nav class="breadcrumb"><?php get_imz_breadcrumbs(get_the_ID()); ?></nav>
			<article class="entry">
				<header class="entry-header">
					<h1 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
					<p class="date"><?php the_date(); ?></p>
				</header>
        		<div class="entry-body"><?php the_content(); ?></div>
			</article>
    	<?php endwhile; endif; ?>
		<?php the_post_navigation(); ?>
		</main>
		<aside class="sidebar-container">
		<?php if ( is_active_sidebar( 'sidebar-widget-area' ) ) : ?>
		<?php dynamic_sidebar( 'sidebar-widget-area' ); ?>
		<?php endif; ?>
		</aside>
	</div>
	<div class="footer-widget-area">
	<?php if ( is_active_sidebar( 'footer-widget-area' ) ) : ?>
	<?php dynamic_sidebar( 'footer-widget-area' ); ?>
	<?php endif; ?>
	</div>
	<footer class="site-footer">
		<p>Copyright © 2022 · <a href="https://imuza.com">IMUZA.com</a></p>
	</footer>
	<nav class="secondary-nav">
		<?php wp_nav_menu( array( 'theme_location' => 'secondary-nav' ) ); ?>
	</nav>
</div>
</body>
</html>

03テンプレート階層

index.php をはじめとするテンプレートファイルはテーマディレクトリ直下に置きますが、下の表示設定との関係で結構ややこしいですね。おそらく WordPress の成立過程が、単純なブログシステムから始まったもののいまや不動の CMS の地位を得てしまったことが影響しているのでしょう。

テンプレート階層のドキュメントは次のリンク先にありますが、「フロントページ表示」については読めば読むほど混乱してきます。

ですので、どういうサイト構成にするかから考えたほうがよさそうです。今回はブログですので一般的に次のようになります。最低必要なページだけです。

  • フロントページ(ホームページ、トップページ)
    最新記事、おすすめ記事、よく読まれている記事を5記事程度ずつ表示
  • 個別投稿ページ
  • カテゴリーページ
  • 記事一覧ページ

このサイト構成に必要となるテンプレートを整理しますと、まず、カテゴリーページと記事一覧ページはメインループで該当記事を何記事か表示すればいいわけですから同じテンプレートでいけそうです。

個別投稿ページはすでに single.php としています。

フロントページを index.php でというのは分岐が多くなりごちゃごちゃしますのでやはり単独テンプレートになります。

ということで、今回のテンプレートは次のようになります。

  • index.php ……カテゴリーページ、記事一覧ページ
  • single.php ……個別記事ページ
  • front-page.php ……フロントページ

ブログサイトであれば、これでいけるのではないかと思います。

で、表示設定の「ホームページの設定」ですが、ドキュメントのテンプレート階層を読みますと、フロントページ表示には front-page.php が常に優先されるようにも読めますが、そうではありません。

たとえば、上のような設定の場合は、フロントページのテンプレートには、今回のケースでは index.php が使われます。この設定以外であればフロントページには front-page.php が使われます。

ややこしいですね。

04index.php, カテゴリーページ、記事一覧ページ

ということで、カテゴリーページ、記事一覧ページに使う 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 id="pagetop" class="site-container">
	<header class="site-header">
		<p class="site-title"><a href="<?php echo esc_url(home_url('/')); ?>" title="<?php bloginfo('name'); ?>"><?php bloginfo('name'); ?></a></p>
    	<p class="site-description"><?php bloginfo('description'); ?></p>
	</header>
	<nav class="primary-nav">
		<?php wp_nav_menu( array( 'theme_location' => 'primary-nav' ) ); ?>
	</nav>
	<div class="main-sidebar-container">
		<main class="main-container">
        <h1 class="category-title"><?php (is_category()) ? single_cat_title('映画名: ') : wp_title(''); ?></h1>
    	<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
		<article class="entry">
			<?php if(has_post_thumbnail()): ?>
			<div class="thumbnail">
			<a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(); ?></a>
			</div>
			<?php endif; ?>
			<header class="entry-header">
				<h2 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
				<p class="date"><?php the_date(); ?></p>
				<p class="category"><?php the_category( ', ', 'multiple'); ?></p>
			</header>
        	<div class="entry-body"><?php echo mb_substr( strip_tags( get_the_content() ), 0, 60, 'UTF-8' ) . '...'; ?></div>
		</article>
    	<?php endwhile; endif; ?>
		<?php the_posts_pagination(array('mid_size' => 2, 'prev_text' => '前', 'next_text' => '次' )); ?>
		<?php wp_reset_query(); ?>
		</main>
		<aside class="sidebar-container">
		<?php if ( is_active_sidebar( 'sidebar-widget-area' ) ) : ?>
    	<?php dynamic_sidebar( 'sidebar-widget-area' ); ?>
		<?php endif; ?>
		</aside>
	</div>
	<div class="footer-widget-area">
	<?php if ( is_active_sidebar( 'footer-widget-area' ) ) : ?>
    <?php dynamic_sidebar( 'footer-widget-area' ); ?>
	<?php endif; ?>
	</div>
	<footer class="site-footer">
		<p>Copyright © 2022 · <a href="https://imuza.com">IMUZA.com</a></p>
	</footer>
	<nav class="secondary-nav">
		<?php wp_nav_menu( array( 'theme_location' => 'secondary-nav' ) ); ?>
	</nav>
</div>
</body>
</html>

記事一覧ページは、固定ページの新規追加で、タイトルに「記事一覧」と入れ、URLスラッグに好きな文字列を入れて固定ページを作成します。「サイト URL +スラッグ」がページ URL になります。もちろんパーマリンク設定を投稿名にしている場合です。

ということで、記事一覧ページ、カテゴリーページ(映画名:に変更している)は次のようになります。

ページタイトルの分岐は

<h1 class="category-title"><?php (is_category()) ? single_cat_title('映画名: ') : wp_title(''); ?></h1>

としています。

05front-page.php, フロントページ

フロントページは次のリンク先の表示になることを目標にしています。

ページ内部は、

  • メインビジュアルと下記3項目へのリンク
  • 最新記事5件と記事一覧ページへのリンク
  • おすすめ記事5件とその記事一覧ページへのリンク
  • よく読まれている記事5件とその記事一覧へのリンク

の構成とし、最新記事とおすすめ記事(カテゴリー:recommnd)はサブループで作成します。よく読まれている記事は、いわゆるアクセス数の多い記事ということで、全累計であれば簡単に出来ますし、実際もう出来ているのですが、たとえば直近の24時間などの一定期間の累計にしようとしますとかなり難しそうです。当面はプラグインの WordPress Popular Posts を使うことになりそうです。ですので現在のところ省略しています。

<!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 id="pagetop" class="site-container">
	<header class="site-header">
		<h1 class="site-title"><a href="<?php echo esc_url(home_url('/')); ?>" title="<?php bloginfo('name'); ?>"><?php bloginfo('name'); ?></a></h1>
    	<p class="site-description"><?php bloginfo('description'); ?></p>
	</header>
	<nav class="primary-nav">
		<?php wp_nav_menu( array( 'theme_location' => 'primary-nav' ) ); echo PHP_EOL; ?>
	</nav>
	<div class="main-sidebar-container">
		<main class="main-container">
			<div class="main-visual">
				<nav class="section-link">
					<a href="#latest-articles" class="section-link-item">最新映画レビュー</a>
					<a href="#recommend-articles" class="section-link-item">おすすめ映画</a>
					<a href="#block-13" class="section-link-item">よく読まれている記事</a>
				</nav>
			</div>
			<section id="latest-articles" class="">
				<h2 class="section-title">最新映画レビュー</h2>
				<?php
			    $query = new WP_Query(array('posts_per_page' => 5));
				if ( $query->have_posts() ) :
					while ( $query->have_posts() ) : $query->the_post();
				?>
				<article class="entry">
				<?php if(has_post_thumbnail()): ?>
					<div class="thumbnail">
						<a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(); ?></a>
					</div>
				<?php endif; ?>
					<header class="entry-header">
						<h2 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
						<p class="date"><?php the_date(); ?></p>
						<p class="category"><?php the_category( ', ', 'multiple'); ?></p>
					</header>
       				<div class="entry-body"><?php echo mb_substr( strip_tags( get_the_content() ), 0, 60, 'UTF-8' ) . '...'; ?></div>
				</article>
				<?php endwhile; endif; ?>
       			<?php wp_reset_postdata(); ?>
				<div class="see-more"><a href="/archives">最新レビューを一覧で見る</a></div>
			</section>

       		<section id="recommend-articles" class="">
       			<h2 class="section-title">おすすめ映画</h2>
       			<?php
           		$query = new WP_Query(
           			array(
			            'category_name' => 'recommend',
			            'posts_per_page' => 5,
            		)
           		);
				if ( $query->have_posts() ) :
					while ( $query->have_posts() ) : $query->the_post(); 
				?>
				<article class="entry">
				<?php if(has_post_thumbnail()): ?>
					<div class="thumbnail">
						<a href="<?php the_permalink(); ?>"><?php the_post_thumbnail(); ?></a>
					</div>
				<?php endif; ?>
					<header class="entry-header">
						<h2 class="entry-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
						<p class="date"><?php the_date(); ?></p>
						<p class="category"><?php the_category( ', ', 'multiple'); ?></p>
					</header>
       				<div class="entry-body"><?php echo mb_substr( strip_tags( get_the_content() ), 0, 60, 'UTF-8' ) . '...'; ?></div>
				</article>
    			<?php endwhile; endif; ?>
       			<?php wp_reset_postdata(); ?>
				<div class="see-more"><a href="/category/recommend/">おすすめ映画を一覧で見る</a></div>
			</section>
   		</main>
	</div>
	<div class="footer-widget-area">
	<?php if ( is_active_sidebar( 'footer-widget-area' ) ) : ?>
   		<?php dynamic_sidebar( 'footer-widget-area' ); ?>
	<?php endif; ?>
	</div>
	<footer class="site-footer">
		<p>Copyright © 2022 · <a href="https://imuza.com">IMUZA.com</a></p>
	</footer>
	<nav class="secondary-nav">
		<?php wp_nav_menu( array( 'theme_location' => 'secondary-nav' ) ); ?>
	</nav>
</div>
</body>
</html>

現在のフロントページはこんな感じで出来上がっています。メインビジュアルは作業中に間違えないように目標のサイトとは別のものにしています。

左がフロントページのトップ、右がおすすめ映画5記事の頭の部分です。

これである程度格好がつきましたので、次はデスクトップの表示など CSS を触ってみようと思います。