Cocoon カスタムテンプレート 新着記事だけ全文表示 備忘録

Cocoon

Cocoon 子テーマ使用時に、新着記事だけ全文表示するテンプレートカスタマイズを行った際の技術的な備忘録です。
ほとんど知識がない状態で着手したため、非常に長い記事です。

細かいことはいいから導入だけしたい方は、こちらの記事へどうぞ。

スポンサーリンク

実現方法の調査

まず、Cocoon 公式サイトで「全文表示」で検索すると、カスタマイズ質問コミュニティに以下のような質問がありました。

「最初だけ本文表示」がしたいです
初めまして。検索しても見つからなかったので、質問させてください。 Simplicityにあった、リストの「最初だけ本文表示」が廃止されているようなのですが、なんとかして実現する方法はないでしょうか?list.phpを書き換えてみたりしたのですが、うまくいきません・・・。
最新の記事だけ全文表示したい
先日 simplicity2 から cocoon にテーマを変更しました。まだいろいろといじっている最中で機能を把握していないのですが、トップページ(インデックスリスト)の表示で、一番最新の記事だけ全文表示にできないでしょうか?#確か simplicity2 にはその設定があったような気が。
複数投稿の全文表示
cocoon を利用して複数の投稿の全文を一度に表示させたいのですが、可能でしょうか。参考にしているサイトは以下のブログになります。

回答としては、Cocoon としては全文表示機能はなく、サポート対象外だけど、テンプレートカスタマイズで実現可能なようです。

1件目の質問には結構具体的な回答や質問者の実施策も書かれています。

Cocoon テンプレート変更概要

テンプレートをいじる方法については、公式の以下のドキュメントが参考になります。

子テーマで上書きカスタマイズ利用できるテンプレートの場所
CocoonテーマのHTMLを変更したかったり、PHP処理を書き加えたかったり、テンプレートファイルを編集する際の基本情報です。

変更したいパーツの php ファイルだけ、子テンプレートの該当フォルダに設置することで可能なようです。

コアな部分やオリジナルファイルを直にいじらずに、テンプレート変更だけで結構いじれてしまうのが Cocoon のいいところですね。

フロントページの構成

Cocoon のテンプレート変更概要はわかったのですが、今回はフロントページだけ変更したいので、フロントページがどういうパーツで表示されているか調べました。

基本テンプレート階層構造

Cocoon も WordPress のテンプレート階層構造に則ってつくられているので、根っこの部分は WordPress の以下のドキュメントが参考になります。

テンプレート階層 - WordPress Codex 日本語版

ホームページ表示

サイトフロントページ、または固定ページの上にあるブログ投稿インデックスページの表示に使用されるテンプレートファイル。注意: サイトフロントページ上にある場合、フロントページテンプレートは、ブログ投稿インデックス (ホーム) テンプレートに優先します。

1. home.php
2. index.php

https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E9%9A%8E%E5%B1%A4#.E3.83.9B.E3.83.BC.E3.83.A0.E3.83.9A.E3.83.BC.E3.82.B8.E8.A1.A8.E7.A4.BA

サイト訪問時、home.php → index.php の順にテンプレートが適用されるようです。

Cocoon での使用テンプレート確認

Cocoon では home.php が存在しないので、index.php がフロントページで読まれているテンプレートになります。
Cocoon はさらに細かいパーツごとにテンプレートが分けられているので、コードを見ながらどのテンプレートが使われているか確認していきます。

index.php

index.php
<?php
/**
 * Cocoon WordPress Theme
 * @author: yhira
 * @link: https://wp-cocoon.com/
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 */
if ( !defined( 'ABSPATH' ) ) exit; ?>
<?php get_header(); ?>

<?php
////////////////////////////
//一覧表示
///////////////////////
if (!is_user_agent_live_writer()) {
  //通常表示
  get_template_part('tmp/list');
} else {
  //ブログエディターLive Writerでテーマ取得の際
  get_template_part('tmp/live-writer');
}
?>

<?php get_footer(); ?>

17行目から「tmp/list」が読まれているのがわかります。

tmp/list.php

tmp/list.php
… 省略 …
<?php
  if (is_front_index_page() && is_front_page_type_tab_index()) {
    get_template_part('tmp/list-tab-index');
  } elseif (is_front_index_page() && is_front_page_type_category()) {
    get_template_part('tmp/list-category');
  } elseif ((is_front_index_page() && is_front_page_type_category_2_columns()) || is_front_index_page() && is_front_page_type_category_3_columns()) {
    get_template_part('tmp/list-category-columns');
  } else {
    get_template_part('tmp/list-index');
  }
?>

… 省略 …

やや大きいファイルなので一部抜粋しました。
条件分岐は、Cocoon設定 > 投稿 > リスト設定の以下の設定による分岐です。

私の「一覧」設定の場合は、「tmp/list-index」が読まれています。

tmp/list-index

tmp/list-index.php
… 省略 …
<?php
////////////////////////////
//一覧の繰り返し処理
////////////////////////////
$count = 0;
if (have_posts()) : // WordPress ループ
  while (have_posts()) : the_post(); // 繰り返し処理開始
    $count++;
    set_query_var( 'count', $count );
    get_template_part('tmp/entry-card');

… 省略 …

やや大きいファイルなので一部抜粋しました。
「一覧の繰り返し」とあるように、ここで投稿毎に「tmp/entry-card」テンプレートを使用していることがわかります。

「tmp/entry-card」というのが、ブログカード表示するためのテンプレートなので、これを全文表示するテンプレートに変えてやればよさそうです。

影響範囲の確認

ここまでで、以下の順にテンプレートが読まれて、tmp/list-index.php をいじればよさそうなのはわかりました。

  1. index.php
  2. tmp/list.php
  3. tmp/list-index.php

ですが、tmp/list-index.php をいじると index.php、tmp/list.php を使っている他のページにまで影響が出かねないため、他にどこからこれらのテンプレートが使われているかを確認します。

index.php

WordPress のテンプレート階層構造と、cocoon-master フォルダの直下のファイルを照らし合わせて、index.php を使用するページを確認します。

上記の参考ページ内で「index.php」を検索し、「index.php」より優先順が上のテンプレートが cocoon-master フォルダの直下になければ、index.php が使われているということになります。

結果、以下のアーカイブ表示系で index.php が使われることがわかりました。

  • カテゴリー表示
  • タグ表示
  • カスタム分類表示
  • カスタム投稿タイプ表示
  • 作成者表示
  • 日付別表示
  • Embeds

これらのページでは、新着投稿を全文表示したくないので、tmp/list-index.php を単純にいじるだけでは具合が悪そうです。

tmp/list.php

このファイルは Cocoon オリジナルのテンプレートファイルなので、「’tmp/list’」で cocoon-master フォルダ配下を grep して、index.php 以外から「get_template_part(‘tmp/list’)」が見つかれば、他でも使用されていることになります。

が、見つからなかったのでこれは影響なさそうです。

tmp/list-index.php

上記の tmp/list.php と同様の方法で tmp/list.php 以外からの使用を調べます。

tmp\list-tab-index.php から使用されていますが、上記の通りフロントページタイプ設定で「タブ一覧」を設定していた場合に使用されるテンプレートです。

将来「タブ一覧」設定にすることも見越して対応しておくのがベストですが、ひとまず「一覧」設定の場合は無視することにします。

変更方法検討

index.php を使用するページが多かったため、フロントページでのみ、新着投稿を全文表示にする方法を検討します。

2020/9/10

変更方法の再検討と再実装を行いました。
新記事へのリンクを貼っておきます。

過去の記事を一旦取り下げさせていただきます。

失敗とその対策

当初、tmp/list.php の条件分岐にフロントページのときのみ別テンプレートを使うように条件を加えて作り進めました。

が、完成していざ表示して見ると、投稿内のコードのハイライト設定が効いておらず、原因を調べると「highlight.js」というスクリプトが読まれていませんでした。

通常このスクリプトはヘッダやフッタ生成時にリンクが埋め込まれるのですが、その際に現在のページが個別投稿ページか個別ページでないと埋め込みが行われないようです。
is_singular() などの関数で検索すると、現在のページタイプに依存するものが他にも存在し、そこを修正するとテンプレート以外のファイルをいじる必要があるため、一覧表示用のテンプレート index.php をベースに全文表示するのはうまくなさそうという結論に至りました。

フロントページで簡単に is_singular() が true になる設定を探したところ、「ホームページの表示」設定で固定ページをホームページに設定するとうまくいったので、固定ページ表示テンプレートをベースにすることにしました。

固定ページ表示

固定ページ (page 投稿タイプ) の表示に使用されるテンプレートファイル。

1. カスタムテンプレートファイル – ページ作成画面の「テンプレート」ドロップダウンメニューで選択したテンプレート名。get_page_templates()参照。
2. page-{slug}.php – 固定ページのスラッグが recent-news ならば WordPress は page-recent-news.php を探す。

https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E9%9A%8E%E5%B1%A4#Page_display

上記の 2. を使って、固定ページではなく投稿ページ一覧を表示するテンプレートを新たに作ることにしました。

実装

投稿ページリストの新着投稿のみを全文表示するテンプレート

index.php、tmp/list.php、tmp/list-index.php、tmp/pagination.php をコピペでひとまとめにし、適宜変更したテンプレートファイルを作ります。

page-list-index-full.php
<?php // 投稿ページリストの新着投稿のみを全文表示する
/**
 * Cocoon WordPress Theme
 * @author: yhira
 * @link: https://wp-cocoon.com/
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 */
if ( !defined( 'ABSPATH' ) ) exit;

if (!is_amp()) {
   get_header();
 } else {
   get_template_part('tmp/amp-header');
 }


////////////////////////////
//インデックストップ広告
////////////////////////////
if (is_ad_pos_index_top_visible() && is_all_adsenses_visible()){
  //レスポンシブ広告
  get_template_part_with_ad_format(get_ad_pos_index_top_format(), 'ad-index-top', is_ad_pos_index_top_label_visible());
};

////////////////////////////
//インデックスリストトップウィジェット
////////////////////////////
if ( is_active_sidebar( 'index-top' ) ){
  dynamic_sidebar( 'index-top' );
};

////////////////////////////
// トップシェアボタン
////////////////////////////
//SNSトップシェアボタンの表示
if (is_sns_top_share_buttons_visible() &&
  //フロントページトップシェアボタンの表示
  (is_front_page() && !is_paged() && is_sns_front_page_top_share_buttons_visible())
){
  get_template_part_with_option('tmp/sns-share-buttons', SS_TOP);
}
?>




<div id="list" class="<?php echo get_index_list_classes(); ?>">
<?php
global $query_string;
query_posts( $query_string . '&post_type=post' );	// 投稿クエリに書き換え
////////////////////////////
//一覧の繰り返し処理
////////////////////////////
$count = 0;
if (have_posts()) : // WordPress ループ
  while (have_posts()) : the_post(); // 繰り返し処理開始
    $count++;
    set_query_var( 'count', $count );
    
    // 現在のページ番号を取得
    $current_pgae = get_query_var( 'paged' ); 
    $current_pgae = $current_pgae == 0 ? '1' : $current_pgae;
    
    if ( ( $current_pgae == 1 ) && ( $count == 1 ) ) {
      get_template_part('tmp/content-in-home');
      echo '<hr noshade class="newest-post">';
    }
    else {
      get_template_part('tmp/entry-card');
    }

    //インデックスミドルに広告を表示してよいかの判別
    if (is_ad_pos_index_middle_visible() && is_index_middle_ad_visible($count) && is_all_adsenses_visible()) {
      get_template_part_with_ad_format(get_ad_pos_index_middle_format(), 'ad-index-middle', is_ad_pos_index_middle_label_visible());
    }

    ////////////////////////////
    //インデックスリストミドルウィジェット
    ////////////////////////////
    if ( is_active_sidebar( 'index-middle' ) && is_index_middle_widget_visible($count) ){
      dynamic_sidebar( 'index-middle' );
    };

  endwhile; // 繰り返し処理終了 ?>
<?php else : // ここから記事が見つからなかった場合の処理
  get_template_part('tmp/list-not-found-posts');
endif;
?>
</div><!-- .list -->




<?php
////////////////////////////
//インデックスボトム広告
////////////////////////////
if (is_ad_pos_index_bottom_visible() && is_all_adsenses_visible()){
  //レスポンシブ広告のフォーマットにrectangleを指定する
  get_template_part_with_ad_format(get_ad_pos_index_bottom_format(), 'ad-index-bottom', is_ad_pos_index_bottom_label_visible());
};

////////////////////////////
//インデックスリストボトムウィジェット
////////////////////////////
if ( is_active_sidebar( 'index-bottom' ) ){
  dynamic_sidebar( 'index-bottom' );
};

////////////////////////////
//フロントページボトムシェアボタン
////////////////////////////
//SNSボトムシェアボタンの表示
if (is_sns_bottom_share_buttons_visible() && !is_paged() &&
  (
  //フロントページボトムシェアボタンの表示
  (is_front_page() && is_sns_front_page_bottom_share_buttons_visible()) ||
  //カテゴリーページトップシェアボタンの表示
  (is_category() && is_sns_category_bottom_share_buttons_visible()) ||
  //タグページトップシェアボタンの表示
  (is_tag() && is_sns_tag_bottom_share_buttons_visible())
  )

){
  get_template_part_with_option('tmp/sns-share-buttons', SS_BOTTOM);
}

////////////////////////////
//フロントページフォローボタン
////////////////////////////
//SNSフォローボタンの表示
if (is_sns_follow_buttons_visible() && !is_paged() &&
  (
    //フロントページフォローボタンの表示
    (is_front_page() && is_sns_front_page_follow_buttons_visible()) ||
    //カテゴリーページボトムフォローボタンの表示
    (is_category() && is_sns_category_follow_buttons_visible()) ||
    //タグページボトムフォローボタンの表示
    (is_tag() && is_sns_tag_follow_buttons_visible())
  )

){
  get_template_part_with_option('tmp/sns-follow-buttons', SF_BOTTOM);
}

////////////////////////////
//ページネーション
////////////////////////////

//ページ情報の取得
global $wp_query;
//全ページ数
$pages = $wp_query->max_num_pages;
if(!$pages){
  $pages = 1;
}

//現在のページ番号
$paged = get_query_var( 'paged' );
if(empty($paged)) $paged = 1;

//ページが1ページしかない場合は出力しない
if($pages != 1) {
  //次のページ番号
  if ( $pages == $paged ) {
    $next_page_num = $paged;
  } else {
    $next_page_num = $paged + 1;
  }

  //現在のページ番号が全ページ数よりも少ないときは「次のページ」タグを出力
  if ( $paged < $pages ) {
    $url = get_pagenum_link($next_page_num);
    //$url = get_query_removed_url($url);
    echo '<div class="pagination-next"><a href="'.esc_url($url).'" class="pagination-next-link key-btn">'.__( '次のページ', THEME_NAME ).'</a></div>';
  }

}
?>


<div class="pagination">
  <?php global $wp_rewrite;
  $paginate_base = get_pagenum_link(1);
  if(strpos($paginate_base, '?') || ! $wp_rewrite->using_permalinks()){
    $paginate_format = '';
    $paginate_base = add_query_arg('paged','%#%');
  }
  else{
    $paginate_format = (substr($paginate_base,-1,1) == '/' ? '' : '/') .
    user_trailingslashit('page/%#%/','paged');;
    $paginate_base .= '%_%';
  }

  echo paginate_links(array(
    'base' => $paginate_base,
    'format' => $paginate_format,
    'total' => $wp_query->max_num_pages,
    'mid_size' => 2,
    'current' => ($paged ? $paged : 1),
    'prev_text' => '<span class="fa fa-angle-left" aria-hidden="true"></span>',
    'next_text' => '<span class="fa fa-angle-right" aria-hidden="true"></span>',
  ));
  ?>
</div><!-- /.pagination -->

<?php
wp_reset_query();

////////////////////////////
//メインカラム追従領域
////////////////////////////
get_template_part('tmp/main-scroll');
?>


<?php get_footer(); ?>

変更箇所の概要は以下の通りです。

クエリの上書き

global $query_string;
query_posts( $query_string . '&post_type=post' );	// 投稿クエリに書き換え
wp_reset_query();

クエリの投稿タイプを一般投稿(’post’)で上書きします。
先述の通り、このテンプレートが呼ばれるのは固定ページ表示クエリなので、何もしなければ固定ページを表示することになってしまうため、一般投稿で上書きしています。

WordPress Codex によると query_posts() の使用は非推奨とされています。

テンプレートタグ/query posts - WordPress Codex 日本語版

今回非推奨関数を使うに至った理由をメモしておきます。

  • 推奨される代替案 pre_get_posts アクションは固定ページのリクエストでは動作しない
  • この関数の欠点がまさにやりたいことなため問題ない
    • メインループを変更する
      ⇒ メインループを生成するクエリを書き換えたい
    • ページ送り
      ⇒ ページ送りも書き換えられたクエリに則らせたい
       オリジナルクエリの保持(ページングなど)は実施済み

全文表示、ブログカード表示の切り分け

    // 現在のページ番号を取得
    $current_pgae = get_query_var( 'paged' ); 
    $current_pgae = $current_pgae == 0 ? '1' : $current_pgae;
    
    if ( ( $current_pgae == 1 ) && ( $count == 1 ) ) {
      get_template_part('tmp/content-in-home');
      echo '<hr noshade class="newest-post">';
    }
    else {
      get_template_part('tmp/entry-card');
    }

1ページ目かつリストの一番上の投稿を全文表示(tmp/content-in-home テンプレート使用)、それ以外をブログカード表示(tmp/entry-card テンプレート使用)に切り分けます。

新たなクエリでのページ番号取得

//現在のページ番号
$paged = get_query_var( 'paged' );

既存の「global $paged;」だと、クエリを書き換える前のページ番号になってしまうため、ページ番号を再取得しています。

フロントページでの全文表示テンプレート

個別投稿ページテンプレート参考に、新規ファイル tmp/index-content.php を作ります。

フロントページの構成と同じ要領で個別投稿ページで使用されるテンプレートを確認します。

  • single.php
  • tmp/single-contents.php
  • tmp/content.php

single.php はヘッダフッタの作成部分で page-list-index-full.php で作成済みのため無視し、tmp/single-contents.php、tmp/content.php をコピペでひとまとめにし、適宜変更したテンプレートファイルを作ります。

tmp/index-content.php
<?php // single-contents 代替
/**
 * Cocoon WordPress Theme
 * @author: yhira
 * @link: https://wp-cocoon.com/
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 */
if ( !defined( 'ABSPATH' ) ) exit;
$article_id_attr = null;
if (is_front_page_type_index()) {
  $article_id_attr = ' id="post-'.get_the_ID().'"';
}
?>

<?php //パンくずリストがメイントップの場合
if (is_single_breadcrumbs_position_main_top()){
	get_template_part('tmp/breadcrumbs-forced');
} ?>

<article id="post-<?php the_ID(); ?>" <?php post_class('article') ?> itemscope="itemscope" itemprop="blogPost" itemtype="https://schema.org/BlogPosting">

	<?php //タイトル上の広告表示
	if (is_ad_pos_above_title_visible() && is_all_adsenses_visible()){
		get_template_part_with_ad_format(get_ad_pos_above_title_format(), 'ad-above-title', is_ad_pos_above_title_label_visible());
	}; ?>

	<?php //投稿タイトル上ウイジェット
	if ( is_single() && is_active_sidebar( 'above-single-content-title' ) ): ?>
		<?php dynamic_sidebar( 'above-single-content-title' ); ?>
	<?php endif; ?>

	<?php //固定ページタイトル上ウイジェット
	if ( is_page() && is_active_sidebar( 'above-page-content-title' ) ): ?>
		<?php dynamic_sidebar( 'above-page-content-title' ); ?>
	<?php endif; ?>

	<?php //タイトル上のカテゴリー・タグ
	if (is_category_tag_display_position_title_top() && is_single()) {
		get_template_part('tmp/categories-tags');
	} ?>

<a href="<?php echo esc_url(get_the_permalink()); ?>" class="entry-card-wrap a-wrap border-element cf" title="<?php echo esc_attr(get_the_title()); ?>">

	<header class="article-header entry-header">
		<h1 class="entry-title" itemprop="headline">
			<?php
			if (is_wpforo_plugin_page()) {
				echo wp_get_document_title();
			} else {
				the_title();
			}
			 ?>
		</h1>

		<?php //レビュー表示
		if (is_the_page_review_enable()) {
			echo '<div class="review-rating">';
			echo get_rating_star_tag(get_the_review_rate(), 5, true);
			echo '</div>';
		}
		?>

		<?php //タイトル下の広告表示
		if (is_ad_pos_below_title_visible() && is_all_adsenses_visible()){
			get_template_part_with_ad_format(get_ad_pos_below_title_format(), 'ad-below-title', is_ad_pos_below_title_label_visible());
		}; ?>

		<?php //投稿タイトル下ウイジェット
		if ( is_single() && is_active_sidebar( 'below-single-content-title' ) ): ?>
			<?php dynamic_sidebar( 'below-single-content-title' ); ?>
		<?php endif; ?>

		<?php //固定ページタイトル下ウイジェット
		if ( is_page() && is_active_sidebar( 'below-page-content-title' ) ): ?>
			<?php dynamic_sidebar( 'below-page-content-title' ); ?>
		<?php endif; ?>

		<?php //アイキャッチ挿入
		get_template_part('tmp/eye-catch');

		do_action('singular_eye_catch_after');
		?>

		<?php //SNSトップシェアボタンの表示
		if (is_sns_top_share_buttons_visible() &&
			(
				//投稿ページトップシェアボタンの表示
				(is_single() && is_sns_single_top_share_buttons_visible()) ||
				//固定するページトップシェアボタンの表示
				(is_page() && is_sns_page_top_share_buttons_visible())
			)
		){
			get_template_part_with_option('tmp/sns-share-buttons', SS_TOP);
		} ?>


		<?php //投稿日と更新日テンプレート
		get_template_part('tmp/date-tags'); ?>

		<?php //本文上のカテゴリー・タグ
		if (is_category_tag_display_position_content_top() && is_single()) {
			get_template_part('tmp/categories-tags');
		} ?>

		<?php if (is_content_read_time_visible() && is_the_page_read_time_visible() && !is_plugin_fourm_page()): ?>
			<div class="read-time"><?php echo '<span class="fa fa-hourglass-half" aria-hidden="true"></span>
'.sprintf(__( 'この記事は<span class="bold">約%s分</span>で読めます。', THEME_NAME ), get_time_to_content_read(get_the_content())); ?></div>
		<?php endif; ?>

		 <?php //本文上の広告表示
		if (is_ad_pos_content_top_visible() && is_all_adsenses_visible()){
			get_template_part_with_ad_format(get_ad_pos_content_top_format(), 'ad-content-top', is_ad_pos_content_top_label_visible());
		}; ?>

		<?php //投稿本文上ウイジェット
		if ( is_single() && is_active_sidebar( 'single-content-top' ) ): ?>
			<?php dynamic_sidebar( 'single-content-top' ); ?>
		<?php endif; ?>

		<?php //固定ページ本文上ウイジェット
		if ( is_page() && is_active_sidebar( 'page-content-top' ) ): ?>
			<?php dynamic_sidebar( 'page-content-top' ); ?>
		<?php endif; ?>

	</header>
</a>

	<?php //投稿・固定ページ本文前のアクションフック
	do_action('singular_entry_content_before'); ?>

	<div class="entry-content cf<?php echo get_additional_entry_content_classes(); ?>" itemprop="mainEntityOfPage">
	<?php //記事本文の表示
		the_content( '続きを読む' ); ?>
	</div>

	<?php ////投稿・固定ページ本文後のアクションフック
	do_action('singular_entry_content_after'); ?>

	<?php //マルチページ用のページャーリンク
	get_template_part('tmp/pager-page-links'); ?>
	
	<?php	// カスタムcss
	$custom_css = get_post_meta(get_the_ID(), '_custom_css', true);
	if ($custom_css) {
		echo '<!-- '.THEME_NAME.' Custom CSS -->'.PHP_EOL;
		echo '<style>' . $custom_css . '</style>'.PHP_EOL;
	}
	?>
	
	<?php	// カスタムjs
	$custom_js = get_post_meta(get_the_ID(), '_custom_js', true) ;
	if ($custom_js) {
		echo '<!-- '.THEME_NAME.' Custom JS -->'.PHP_EOL;
		echo '<script type="text/javascript">' . $custom_js . '</script>'.PHP_EOL;
	}
	?>

	<footer class="article-footer entry-footer">

		<?php //投稿本文下ウイジェット
		if ( is_single() && is_active_sidebar( 'single-content-bottom' ) ): ?>
			<?php dynamic_sidebar( 'single-content-bottom' ); ?>
		<?php endif; ?>

		<?php //固定ページ本文下ウイジェット
		if ( is_page() && is_active_sidebar( 'page-content-bottom' ) ): ?>
			<?php dynamic_sidebar( 'page-content-bottom' ); ?>
		<?php endif; ?>

		<?php //本文下ページ送りナビ
		if (is_post_navi_position_under_content()) {
			get_template_part('tmp/pager-post-navi');
		} ?>

		<?php //本文下のカテゴリー・タグ
		if (is_category_tag_display_position_content_bottom() && is_single()) {
			get_template_part('tmp/categories-tags');
		} ?>

		<?php //本文下の広告表示
		if (is_ad_pos_content_bottom_visible() && is_all_adsenses_visible()){
			//レスポンシブ広告のフォーマットにrectangleを指定する
			get_template_part_with_ad_format(get_ad_pos_content_bottom_format(), 'ad-content-bottom', is_ad_pos_content_bottom_label_visible());
		}; ?>

		<?php //SNSシェアボタン上の広告表示
		if (is_ad_pos_above_sns_buttons_visible() && is_all_adsenses_visible()){
			get_template_part_with_ad_format(get_ad_pos_above_sns_buttons_format(), 'ad-above-sns-buttons', is_ad_pos_above_sns_buttons_label_visible());
		}; ?>

		<?php //投稿SNSボタン上ウイジェット
		if ( is_single() && is_active_sidebar( 'above-single-sns-buttons' ) ): ?>
			<?php dynamic_sidebar( 'above-single-sns-buttons' ); ?>
		<?php endif; ?>

		<?php //固定ページSNSボタン上ウイジェット
		if ( is_page() && is_active_sidebar( 'above-page-sns-buttons' ) ): ?>
			<?php dynamic_sidebar( 'above-page-sns-buttons' ); ?>
		<?php endif; ?>

		<?php //SNSボトムシェアボタンの表示
		if (is_sns_bottom_share_buttons_visible() &&
			(
				//投稿ページボトムシェアボタンの表示
				(is_single() && is_sns_single_bottom_share_buttons_visible()) ||
				//固定するページボトムシェアボタンの表示
				(is_page() && is_sns_page_bottom_share_buttons_visible())
			)
		){
			get_template_part_with_option('tmp/sns-share-buttons', SS_BOTTOM);
		} ?>

		<?php //SNSフォローボタン
		if (
			is_sns_follow_buttons_visible() &&
			(
				//投稿ページフォローボタンの表示
				(is_single() && is_sns_single_follow_buttons_visible()) ||
				//固定するページフォローボタンの表示
				(is_page() && is_sns_page_follow_buttons_visible())
			)
		){
			get_template_part_with_option('tmp/sns-follow-buttons', SF_BOTTOM);
		} ?>

		<?php //SNSシェアボタン上の広告表示
		if (is_ad_pos_below_sns_buttons_visible() && is_all_adsenses_visible()){
			get_template_part_with_ad_format(get_ad_pos_below_sns_buttons_format(), 'ad-below-sns-buttons', is_ad_pos_below_sns_buttons_label_visible());
		}; ?>

		<?php //投稿SNSボタン下ウイジェット
		if ( is_single() && is_active_sidebar( 'below-single-sns-buttons' ) ): ?>
			<?php dynamic_sidebar( 'below-single-sns-buttons' ); ?>
		<?php endif; ?>

		<?php //固定ページSNSボタン下ウイジェット
		if ( is_page() && is_active_sidebar( 'below-page-sns-buttons' ) ): ?>
			<?php dynamic_sidebar( 'below-page-sns-buttons' ); ?>
		<?php endif; ?>

		<?php //投稿者等表示用のテンプレート
		get_template_part('tmp/footer-meta'); ?>

		<!-- publisher設定 -->
		<?php
		$home_image_url = get_amp_logo_image_url();
		$size = get_image_width_and_height($home_image_url);
		$width = isset($size['width']) ? $size['width'] : 600;
		$height = isset($size['height']) ? $size['height'] : 60;

		$sizes = calc_publisher_image_sizes($width, $height);
		$width = $sizes ? $sizes['width'] : 600;
		$height = $sizes ? $sizes['height'] : 60;
		 ?>
		<div class="publisher" itemprop="publisher" itemscope itemtype="https://schema.org/Organization">
				<div itemprop="logo" itemscope itemtype="https://schema.org/ImageObject">
					<img src="<?php echo $home_image_url; ?>" width="<?php echo $width; ?>" height="<?php echo $height; ?>" alt="">
					<meta itemprop="url" content="<?php echo $home_image_url; ?>">
					<meta itemprop="width" content="<?php echo $width; ?>">
					<meta itemprop="height" content="<?php echo $height; ?>">
				</div>
				<div itemprop="name"><?php bloginfo('name'); ?></div>
		</div>
	</footer>

</article>

<?php //パンくずリストがメインボトムの場合
if (is_single_breadcrumbs_position_main_bottom()){
	get_template_part('tmp/breadcrumbs-forced');
} ?>

<?php //メインカラム追従領域
get_template_part('tmp/main-scroll'); ?>

変更箇所の概要は以下の通りです。

パンくずリストの強制表示

	get_template_part('tmp/breadcrumbs-forced');

既存のパンくずリストテンプレートは、個別投稿やカテゴリページでのみの表示になっているため、現在のページに関わらず表示する tmp/breadcrumbs-forced テンプレートを作ることにしました。

ループ重複の削除

参考にした tmp/content.php の中で、if ( have_posts() ){ … } が行われていますが、tmp/list-index-content.php で既にこの処理を行っているので、重複しないように削除します。

不要コンテンツの削除

個別投稿ではコメントなどが表示されますが、フロントページでは不要と判断したので、それらをごっそり削っています。

カスタムスタイル、カスタムスクリプトの挿入

	<?php	// カスタムcss
	$custom_css = get_post_meta(get_the_ID(), '_custom_css', true);
	if ($custom_css) {
		echo '<!-- '.THEME_NAME.' Custom CSS -->'.PHP_EOL;
		echo '<style>' . $custom_css . '</style>'.PHP_EOL;
	}
	?>
	
	<?php	// カスタムjs
	$custom_js = get_post_meta(get_the_ID(), '_custom_js', true) ;
	if ($custom_js) {
		echo '<!-- '.THEME_NAME.' Custom JS -->'.PHP_EOL;
		echo '<script type="text/javascript">' . $custom_js . '</script>'.PHP_EOL;
	}
	?>

従来はヘッダ作成時に挿入されるカスタム css やカスタム js ですが、すでにヘッダは作成済みなので body タグ内に挿入しています。

ヘッダで読み込まれるスクリプトなどは、前述の通り固定ページ用のものなので、投稿ページ用のカスタム~系をここで挿入します。

個別投稿ページへのリンク

<a href="<?php echo esc_url(get_the_permalink()); ?>" class="entry-card-wrap a-wrap border-element cf" title="<?php echo esc_attr(get_the_title()); ?>">

個別投稿ページへのジャンプ方法として、記事ヘッダにリンクを貼りました。

強制パンくずリスト表示テンプレート

投稿ページパンくずリストテンプレート tmp/breadcrumbs.php を参考に、新規ファイル tmp/breadcrumbs-forced.php を作ります。

tmp/breadcrumbs-forced.php
<?php //カテゴリ用のパンくずリスト
/**
 * Cocoon WordPress Theme
 * @author: yhira
 * @link: https://wp-cocoon.com/
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 */
if ( !defined( 'ABSPATH' ) ) exit;

if (is_single_breadcrumbs_visible()){
  $cats = get_the_category();
  //メインカテゴリが指定してある場合は該当カテゴリーを適用
  $main_cat_id = get_the_page_main_category();
  if ($main_cat_id && in_category($main_cat_id)) {
    $cat = get_category($main_cat_id);
  }
  //メインカテゴリがない場合は先頭のカテゴリを適用
  if (!$cat) {
    $cat = $cats[0];
  }
  // $cat = (is_single() && isset($cats[0])) ? $cats[0] : get_category(get_query_var("cat"));
  if($cat && !is_wp_error($cat)){
    $echo = null;
    $root_text = __( 'ホーム', THEME_NAME );
    $root_text = apply_filters('breadcrumbs_single_root_text', $root_text);
    //var_dump($par);
    echo '<div id="breadcrumb" class="breadcrumb breadcrumb-category'.get_additional_single_breadcrumbs_classes().'" itemscope itemtype="https://schema.org/BreadcrumbList">';
    echo '<div class="breadcrumb-home" itemscope itemtype="https://schema.org/ListItem" itemprop="itemListElement"><span class="fa fa-home fa-fw" aria-hidden="true"></span><a href="'.esc_url(get_home_url()).'" itemprop="item"><span itemprop="name" class="breadcrumb-caption">'.esc_html($root_text).'</span></a><meta itemprop="position" content="1" /><span class="sp"><span class="fa fa-angle-right" aria-hidden="true"></span></span></div>';
    $count = 1;
    $par = get_category($cat->parent);
    //カテゴリ情報の取得
    $cats = array();
    while($par && !is_wp_error($par) && $par->term_id != 0){
      $cats[] = $par;
      $par = get_category($par->parent);
    }
    //カテゴリの順番入れ替え
    $cats = array_reverse($cats);
    //先祖カテゴリの出力
    foreach ($cats as $par) {
      ++$count;
      //var_dump($par->name);
      $echo .= '<div class="breadcrumb-item" itemscope itemtype="https://schema.org/ListItem" itemprop="itemListElement"><span class="fa fa-folder fa-fw" aria-hidden="true"></span><a href="'.esc_url(get_category_link($par->term_id)).'" itemprop="item"><span itemprop="name" class="breadcrumb-caption">'.esc_html($par->name).'</span></a><meta itemprop="position" content="'.$count.'" /><span class="sp"><span class="fa fa-angle-right" aria-hidden="true"></span></span></div>';
    }
    // 現カテゴリの出力
    ++$count;
    echo $echo.'<div class="breadcrumb-item" itemscope itemtype="https://schema.org/ListItem" itemprop="itemListElement"><span class="fa fa-folder fa-fw" aria-hidden="true"></span><a href="'.esc_url(get_category_link($cat->term_id)).'" itemprop="item"><span itemprop="name" class="breadcrumb-caption">'.esc_html($cat->name).'</span></a><meta itemprop="position" content="'.$count.'" />';
    //ページタイトルを含める場合はセパレーターを表示
    if (is_single_breadcrumbs_include_post()) {
      echo '<span class="sp"><span class="fa fa-angle-right" aria-hidden="true"></span></span>';
    }
    echo '</div>';
    //ページタイトルを含める場合
    if (is_single_breadcrumbs_include_post()) {
      echo '<div class="breadcrumb-item"><span class="fa fa-file-o fa-fw" aria-hidden="true"></span><a href="<?php echo esc_url(get_the_permalink()); ?>"><span class="breadcrumb-caption">'.esc_html(get_the_title()).'</span></a></div>';
    }

    echo '</div><!-- /#breadcrumb -->';
  }
} //is_single_breadcrumbs_visible ?>

変更箇所の概要は以下の通りです。

現在のページによる分岐削除

is_single() などの現在のページ分類による条件を削除します。

個別投稿ページへのリンク

      echo '<div class="breadcrumb-item"><span class="fa fa-file-o fa-fw" aria-hidden="true"></span><a href="<?php echo esc_url(get_the_permalink()); ?>"><span class="breadcrumb-caption">'.esc_html(get_the_title()).'</span></a></div>';

ページタイトル部分に個別投稿ページへのリンクを追加しました。

完成!

今回「page-list-index-full.php」というファイル名にしたので、固定ページのパーマリンクを「list-index-full」にして、「ホームページの表示」設定で「list-index-full」固定ページをホームページに設定すれば、フロントページで新着投稿が全文表示されているのが確認できます。
コードハイライトも適用されて問題も無事解決できました。

よしなしごと

当初は全投稿を全文表示ししようとしていたのですが、実際いじってみるとそうすると都合が悪そうなことが見えてきたのでそのメモになります。

集客のこと

Cocoon は各投稿への訪問数などのカウントや、SEO 最適化などブログの集客に関することをあれこれしてくれており、それが投稿単位に行われているようです。
全文表示にしてしまうと各投稿ページへのジャンプの機会が大幅に損なわれるため、それらの恩恵が受けにくくなってしまいそうです。

カスタムスタイル、カスタムスクリプトのこと

Cocoon は各投稿ごとにカスタムスタイル、カスタムスクリプトを挿入できますが、1ページに複数投稿を全文表示した場合、各投稿のスクリプトなどが衝突を起こすことがあり得ます。
衝突しないように気を付けながら使うのでは、個別に設定できるカスタムスタイル、カスタムスクリプトのメリットが台無しになってしまいます。

見た目のこと

各投稿が短めの twitter くらいシンプルな内容なら全文表示でもよさそうなのですが、これみたいな長文投稿があると一気に可読性が落ちそうです。

と、思うことがあったので、今回のカスタマイズは新着投稿のみ全文表示にしてみました。
Cocoon テンプレートのいじり方が少しわかった気がするので、大変勉強になりました。

コメント