【需要あるのか⁉】Wordpress自作テーマの投稿一覧ページ自体にアイキャッチ画像を設定する方法

はじめに

投稿一覧ページは主にindex.phparchive.phpなどで作成され、投稿一覧に表示される画像は各投稿ページの編集画面で設定されたアイキャッチ画像が読み込まれる仕様になっている。

今回、テーマを自作した際、投稿一覧ページ自体にアイキャッチ画像を設定したかったのだが、普通にアイキャッチ画像を設定しても、ページには最新投稿用のアイキャッチ画像が表示されてしまう

そもそも、投稿一覧ページ自体にアイキャッチ画像を設定することはほぼ無いので、需要がどこまであるか不明だが、この解決方法を見つけたので、一応紹介しようと思う。

事前準備

事前準備として、自作テーマでアイキャッチ画像を表示させるために、functions.phpにアイキャッチ画像を有効化する関数を追加する。

以下の関数をそのままfunctions.phpに追加。

add_theme_support('post-thumbnails');

アイキャッチ画像を表示するthe_post_thumbnail()関数

アイキャッチ画像を表示する関数は、

the_post_thumbnail()

だが、これはループ内でのみ使用可能なので、通常は

<?php if ( has_post_thumbnail()): ?>
	<?php the_post_thumbnail(); ?>
<?php endif; ?>

として使用する。

投稿件数分のアイキャッチ画像を表示するwhile構文

投稿は件数が増減するので、投稿一覧ページで各投稿のアイキャッチ画像を表示するには、投稿がある分全て取得しなければならない。

その場合はwhile構文を使用して取得する。

<?php if(has_post_thumbnail()): ?>
	<?php while(has_post_thumbnail()): ?>
		<?php the_post_thumbnail(); ?>
	<?php endwhile; ?>
<?php endif; ?>

そんな感じで、Wordpressの自作テーマ中に投稿一覧ページ用のindex.phpを自作してみた。

index.phpの作成

index.phpのコードは当初以下の通りにした。

<?php get_header(); ?>

<section>
<?php if ( has_post_thumbnail()): ?>
  <?php the_post_thumbnail(); ?>//投稿一覧ページのアイキャッチ画像を表示(のつもり)
<?php endif; ?>

<h2><?php echo get_the_title( get_option('page_for_posts') ); ?></h2>
<?php if(have_posts()): while(have_posts()): the_post();?>
      <section>
        <div>
          <?php if ( has_post_thumbnail()): ?>
            <?php the_post_thumbnail(array( 200, 200 ));  ?>//個別投稿ページのアイキャッチ画像を表示
          <?php endif; ?>
        </div>
        <div>
          <h3>
            <a href="<?php the_permalink(); ?>">
              <?php the_title(); ?>
            </a>
          </h3>
        </div>  
      </section>
    <?php endwhile; endif; ?>
</section>

<?php get_footer(); ?>

実は、単に5行目の様にすると、最新投稿のアイキャッチ画像を表示してしまい、投稿一覧ページ自体のアイキャッチ画像は表示されない。

どうすれば良いだろうか?

投稿一覧ページを他と区別できれば良いのではないか?

そう思い、Wordpressで用意されている関数でそういうものがないか探したら、やっぱりあった。

ページのID番号を取得するget_option()関数

今回投稿一覧ページはindex.phpを使用し、このindex.phpは固定ページに相当する。このページのID番号が分かれば何とかなるのではないか。

ページのID番号の調べ方は、

ワードプレスの投稿ID・固定ページID・カテゴリーID・タグIDの調べ方 | あかえほ

にて詳しく解説されているのでそれを参照する。

そのID番号の取得は

get_option('page_for_posts')

この関数は、Wordpressの設定→表示設定で「投稿ページ」に指定した固定ページのIDを取得でき、それ故そのページに指定した投稿一覧ページのID番号が取得できる。

アイキャッチ画像のID番号を取得するget_post_thumbnail_id()関数

投稿一覧ページのID番号が取得できたら次は、投稿一覧ページ自体のアイキャッチ画像を識別する。

アイキャッチ画像のID番号も次の関数で取得できる。

get_post_thumbnail_id(そのページのID)

「そのページのID」はget_option('page_for_posts')で取得しているから、次の通りに記述する。

// このページのidを取得する(Wordpressの設定→表示設定で「投稿ページ」に指定した固定ページIDを取得)
$index_page_id = get_option('page_for_posts');
// このページのアイキャッチ画像のidを取得する
$_attachment_id = get_post_thumbnail_id($index_page_id);

これで投稿一覧ページ自体のアイキャッチ画像を識別する事ができるのだが、このまま進めていくとアイキャッチ画像はレスポンシブに対応せず固定サイズのままになる。

アイキャッチ画像のHTMLのimg要素を出力するwp_get_attachment_image()関数

レスポンシブ対応のため、Bootstrapを導入しており、それはHTMLのクラス名に'img-fluid'を指定することで可能になる。

これを設定できるwp_get_attachment_imageを使用する。

この関数はHTMLのimg要素を出力する。

wp_get_attachment_image( $_attachment_id, 'full', false, array('class' => 'img-fluid', 'alt' => $_attachment_alt));
/**
*$_attachment_idは上記で取得したアイキャッチ画像のid
*'full'は画像サイズ
*falseは画像をアイコン画像として扱うかどうかで否を選択
*array('class' => 'img-fluid', 'alt' => $_attachment_alt)で、HTMLのクラス名とついでにalt(下記参照)を設定
*/

//ついでに、このページのアイキャッチ画像のaltテキストも取得
$_attachment_alt = get_post_meta( $_attachment_id, '_wp_attachment_image_alt', true );

これで投稿一覧ページ自体のアイキャッチ画像のHTMLが設定できた。

index.phpの完成

よって、当初記述したindex.phpの5行目を変更したものは以下の通り。

<?php get_header(); ?>

<section>
<?php if ( has_post_thumbnail()): ?>
	<?php 
		//このページのidを取得する(Wordpressの設定→表示設定で「投稿ページ」に指定した固定ページIDを取得)
		$index_page_id = get_option('page_for_posts');
		
		//このページのアイキャッチ画像のidを取得する
		$_attachment_id = get_post_thumbnail_id($index_page_id);
		
		//このページのアイキャッチ画像のaltテキストを取得
		$_attachment_alt = get_post_meta( $_attachment_id, '_wp_attachment_image_alt', true );
		
		/**
		*アイキャッチ画像をレスポンシブ対応にするため、
		*クラス名をBootstrap 5 の'img-fluid'を指定
		*ついでにaltの指定も
		*/
		echo wp_get_attachment_image( $_attachment_id, 'full', false, array('class' => 'img-fluid', 'alt' => $_attachment_alt));
	?>
<?php endif; ?>

<h2><?php echo get_the_title( get_option('page_for_posts') ); ?></h2>
<?php if(have_posts()): while(have_posts()): the_post();?>
      <section>
        <div>
          <?php if ( has_post_thumbnail()): ?>
				<?php the_post_thumbnail(array( 200, 200 ));  ?>
          <?php endif; ?>
        </div>
        <div>
          <h3>
            <a href="<?php the_permalink(); ?>">
              <?php the_title(); ?>
            </a>
          </h3>
        </div>  
      </section>
    <?php endwhile; endif; ?>
</section>

<?php get_footer(); ?>

これで無事投稿一覧ページ自体のアイキャッチ画像が表示されるindex.phpが完成した。

2022/1/31追記

完成したと思ったら…

これで投稿一覧ページ自体(index.php)のアイキャッチ画像も表示されてめでたしめでたし、と思いながら、アイキャッチ画像が設定されていない投稿ページを最新投稿としてみたところ、投稿一覧ページ自体のアイキャッチ画像が、最新投稿の1つ前の投稿のアイキャッチ画像になる、という挙動になることが判明した。

なんで〜〜!? である。

どうもID取得が上手くいかず混線しているようだ。より厳密な方法でIDを識別する必要がある。

そのついでに、アイキャッチ画像は全ページに設定する予定なので、その部分はヘッダー設定(header.php)に統合してしまった方が効率も良さそうである。

ということでアイキャッチ画像の取得方法は、より厳密にIDを識別しつつ、全ページに適用できる汎用性のあるものに改良していくことにする。

投稿件数分のアイキャッチ画像の取得方法の改良(index.php内に記述)

まずは、投稿一覧ページ(index.php)の本文に当たる投稿件数分のアイキャッチ画像の取得をより厳密に行う

上記で完成したと思っていた投稿一覧ページ(index.php)の投稿件数分のアイキャッチ画像の取得方法は、単に

the_post_thumbnail()

としたのみで、厳密ではなかった
より厳密にするために、

  1. 各投稿ページのIDを取得
  2. 各投稿ページのアイキャッチ画像のIDを取得
  3. 各投稿ページのアイキャッチ画像を取得
  4. アイキャッチ画像がない場合、No Image画像を取得

という手順を行う。それをphpに落とし込むと以下の通りになる。

<?php
	//個別投稿ページの諸情報を取得
	$each_page_data = get_page_by_path(basename(get_permalink()), OBJECT, 'post');
	$each_page_id = $each_page_data->ID; //諸情報からIDのみを取得
?>
<!-- アイキャッチ画像がある場合|引数を指定 -->
<?php if ( has_post_thumbnail($each_page_id)): ?>
	<?php
		$img_size = array( 200, 9999 ); //アイキャッチ画像のサイズ設定
		//【独自関数】アイキャッチ画像のHTMLのimg要素を出力
		sz_get_eye_catch_img($each_page_id, $img_size);
	?>
<?php else: ?><!-- アイキャッチ画像が無い場合 -->
	<img src ="<?php echo get_template_directory_uri(); ?>/images/no_image.png"⏎
		class="img-fluid" alt="" style="width:200px;"><!-- no_image画像を表示させる -->
<?php endif; ?>

関数にIDを引数にして厳密に識別するようにしている。
また、2行目のget_page_by_path()の第3引数を「post」とすると各投稿ページを指定でき、その諸々の情報が取得でき、その中にID番号も含まれ、3行目のように書くことでIDが取得できる。

9行目の独自関数は後で解説する。

各ページのアイキャッチ画像の取得方法の改良(eyecatch-header.phpとして独立)

各ページのアイキャッチ画像の取得は、ヘッダー設定(header.php)内で呼び出すことにし、取得方法自体は別ファイル(eyecatch-header.php)にする

各ページを厳密に識別するため、

  1. 固定ページ、投稿一覧ページ、各投稿ページの判別
  2. 各ページのIDを取得
  3. 各ページのアイキャッチ画像のIDを取得
  4. 各ページのアイキャッチ画像を取得

という手順を行う。それをphpに落とし込むと以下の通りになる。

<!--ページの種類判別でページのidを取得-->
<?php if (is_page()): ?><!--固定ページの時-->
	<?php 
		//固定ページの諸情報を取得
		$index_page_data = get_page_by_path(basename(get_permalink()), OBJECT, 'page');
		$index_page_id = $index_page_data->ID; //固定ページのidを取得
	?>

<?php elseif(is_single()): ?><!--個別投稿ページの時-->
	<?php
		//個別投稿ページの諸情報を取得
		$index_page_data = get_page_by_path(basename(get_permalink()), OBJECT, 'post');
		$index_page_id = $index_page_data->ID; //個別投稿ページのidを取得
	?>

<?php else: ?><!--投稿ページに設定した固定ページ(投稿一覧ページ:index.php)の時-->
	<?php 
		$index_page_id = get_option('page_for_posts'); //投稿一覧ページのidを取得
	?>
<?php endif; ?>


<!--アイキャッチ画像のHTMLのimg要素を出力|引数を指定-->
<?php if (has_post_thumbnail($index_page_id)): ?>
	<?php //【独自関数】アイキャッチ画像のHTMLのimg要素を出力
		sz_get_eye_catch_img($index_page_id, 'full');
	?>
<?php endif; ?>

関数にIDを引数にして厳密に識別するようにしている。
また、5行目のget_page_by_path()の第3引数を「page」とすると固定ページを指定でき、その諸々の情報が取得でき、その中にID番号も含まれ、6行目のように書くことでIDが取得できる。

26行目の独自関数は後で解説する。

【独自関数】sz_get_eye_catch_img($page_id, $img_size)の設定(function.php内に記述)

実は生まれてはじめて、プログラムで関数を定義したのである。
このsz_get_eye_catch_img($page_id, $img_size)が独自関数第1号となるのである。
自分が関数を定義するなんて、しかも引数付きで、感慨深い。

それは置いといて、この関数は、第1引数$page_idで表示ページのID、第2引数で画像サイズをセットし、当該ページのアイキャッチ画像IDとalt属性を取得し、最終的にHTMLのimgタグを出力する。

<?php 
    function sz_get_eye_catch_img($page_id, $img_size){
        //ページのアイキャッチ画像のidを取得する
        $eye_catch_id = get_post_thumbnail_id($page_id);
        
        //ページのアイキャッチ画像のaltテキストを取得
        $eye_catch_alt = get_post_meta( $eye_catch_id, '_wp_attachment_image_alt', true );
    
        /**
            *アイキャッチ画像のHTMLのimg要素を出力
            *アイキャッチ画像をレスポンシブ対応にするため、
            *クラス名をBootstrap 5 の'img-fluid'を指定
            *ついでにaltの指定も
        */
        echo wp_get_attachment_image( $eye_catch_id, $img_size, false, array('class' => 'img-fluid', 'alt' => $eye_catch_alt));
    }
?>

この独自関数は、function.phpに記述する。

改良し始めの時は、独自関数にするという発想がなくて、index.phpおよびeyecatch-header.phpに独自関数内のものをいちいち記述していたが、効率が悪い事に気付き、これってもしかして関数定義すれば良いのではないか、でも各ページのアイキャッチ画像IDと投稿一覧ページ本文内で取得する各投稿ページアイキャッチ画像IDが混在しないよう変数を異なるものにしたがそれはどうすれば良いのか、あっ、引数使えばいけるのか、独自関数完成、という流れであった。

付記

wp_get_attachment_image_src()の使用

最初、投稿一覧ページ自体のアイキャッチ画像を取得するphpは以下の通りにしていた。

<?php if ( has_post_thumbnail()): ?>
	<?php // アイキャッチ画像をレスポンシブ対応にする
		// このページのidを取得する(Wordpressの設定→表示設定で「投稿ページ」に指定した固定ページIDを取得)
		$index_page_id = get_option('page_for_posts');
		// このページのアイキャッチ画像のidを取得する
		$_attachment_id = get_post_thumbnail_id($index_page_id);
		/*
		* 画像ファイルの"url"、"width"、"height"属性を配列として返す
		* [0] => url
		* [1] => width
		* [2] => height
		* [3] => 真偽値: リサイズされいている場合は true、元のサイズの場合は false
		*/
		$_attachment = wp_get_attachment_image_src( $_attachment_id,'full' );
		
		//画像のaltテキストの取得
		$_attachment_alt = get_post_meta( $_attachment_id, '_wp_attachment_image_alt', true );
		
		//幅のみ指定とaltの指定
		echo '<img src="'.esc_url($_attachment[0]).'" width="100%" alt="'.$_attachment_alt.'" />';
	?>
<?php endif; ?><!-- Calligraphyページタイトル -->

wp_get_attachment_image_src()という関数を使用していた。

wp_get_attachment_image_url()の使用

投稿一覧ページ自体のアイキャッチ画像のURLを取得したいだけで、wp_get_attachment_image_src()を使うほどではないので、wp_get_attachment_image_url()に代えてみた。

<?php if ( has_post_thumbnail()): ?><!-- Calligraphyページタイトル -->
	<?php 
		//このページのidを取得する(Wordpressの設定→表示設定で「投稿ページ」に指定した固定ページIDを取得)
		$index_page_id = get_option('page_for_posts');
		
		//このページのアイキャッチ画像のidを取得する
		$_attachment_id = get_post_thumbnail_id($index_page_id);
		
		//このページのアイキャッチ画像のurlを取得
		$_attachment = wp_get_attachment_image_url( $_attachment_id,'full' );
		
		//このページのアイキャッチ画像のaltテキストを取得
		$_attachment_alt = get_post_meta( $_attachment_id, '_wp_attachment_image_alt', true );
		
		//アイキャッチ画像をレスポンシブ対応にするためwidth="100%"を指定と、altの指定
		echo '<img src="'.esc_url($_attachment).'" width="100%" alt="'.$_attachment_alt.'" />';
	?>
<?php endif; ?><!-- Calligraphyページタイトル -->

しかし、wp_get_attachment_image()を使用すれば、一気に投稿一覧ページ自体のアイキャッチ画像のHTMLのimg要素まで出力出来るので、これらは採用しなかった。

参照元









コメント

よく読まれている記事

CSSボタンでテキストを天地中央に揃えるとき、なぜボタン高と行高を一緒にするのか

FullCalendarの導入からカレンダー毎の色指定まで

FacebookページのフィードURLを取得しウォールを自サイトに表示