grace-create

WordPressのアイキャッチ画像と同じ扱いで記事中の一番最初の画像をサムネイルで取得する方法

WordPressでブログ記事を書いたときに、読者に興味を持ってもらうための導線の役割をするアイキャッチ画像ですが、残念ながら利用していない方も多いようです。
そこで、願わくばアイキャッチ画像を設定していない場合でも、アーカイブページ等では自動的に記事中から一番最初の画像を取得して表示させたいところです。

『記事中の一番最初の画像をサムネイルで取得する方法』というのは検索すればたくさん出てくると思いますが、表題にあるような『アイキャッチ画像と同じ扱いで』取得する方法は見つけることができなかったのでここに記します。

アイキャッチ画像と同じ扱いで取得したかったのは、画像を正方形に切り抜きトリミングして表示したいという理由からだったのですが、それならCSSの『clip: rect();』を使う方法もあるでしょう。
ただclipだとサイズが違う画像の場合には意図したとおりに表示されないので、ここで紹介するやり方のほうがおすすめだと思います。

解説

まず下準備として set_post_thumbnail_size もしくは add_image_size で画像サイズをセットします。
いずれも $width と $height が 150px で $crop を true にして画像の切り抜きを有効化しています。

set_post_thumbnail_size( 150, 150, true );

もしくは

add_image_size( 'thumbnail', 150, 150, true );

次に、アイキャッチ画像と同じ扱いで画像を取得するために、テンプレートタグ wp get attachment image を使いたいのですが、そのためには記事の一番最初の画像の attachment_id を取得しなければなりません。そのためのコードが以下になります。

//画像URLからIDを取得
function get_attachment_id_by_url( $url ) {
  global $wpdb;
  $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_name = %s";
  preg_match( '/([^\/]+?)(-e\d+)?(-\d+x\d+)?(\.\w+)?$/', $url, $matches );
  $post_name = $matches[1];
  return ( int )$wpdb->get_var( $wpdb->prepare( $sql, $post_name ) );
}

参照:WordPressで画像のURLからアタッチメントIDを取得する

そして、巷に出回っている『記事中の一番最初の画像をサムネイルで取得する』コードを少々弄ります。
7行目で最初の画像のIDを取得して、8行目で wp_get_attachment_image により、アイキャッチ画像を取得するためのテンプレートタグ get_the_post_thumbnail と同じように出力させています。

//画像をサムネイルで出力
function catch_that_image() {
  global $post;
  $first_img = '';
  $output = preg_match_all( '/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches );
  $first_img_src = $matches[1][0];
  $attachment_id = get_attachment_id_by_url( $first_img_src );
  $first_img = wp_get_attachment_image( $attachment_id, 'thumbnail', false, array( 'class' => 'archive-thumbnail' ) );
  if( empty( $first_img ) ){
    $first_img = '<img class="attachment_post_thumbnail" src="' . get_stylesheet_directory_uri() . '/images/no_image.png" alt="No image" />';
  }
  return $first_img;
}

参照:記事内の一番最初の画像を取得してサムネイル画像表示

まとめると以下のようになるので、これをご利用のテーマの functions.php にコピペしてやればOKです。22行目の画像へのパスとファイル名は適宜変更してください。

//画像サイズをセット
set_post_thumbnail_size( 150, 150, true );

//画像URLからIDを取得
function get_attachment_id_by_url( $url ) {
  global $wpdb;
  $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_name = %s";
  preg_match( '/([^\/]+?)(-e\d+)?(-\d+x\d+)?(\.\w+)?$/', $url, $matches );
  $post_name = $matches[1];
  return ( int )$wpdb->get_var( $wpdb->prepare( $sql, $post_name ) );
}

//画像をサムネイルで出力
function catch_that_image() {
  global $post;
  $first_img = '';
  $output = preg_match_all( '/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches );
  $first_img_src = $matches[1][0];
  $attachment_id = get_attachment_id_by_url( $first_img_src );
  $first_img = wp_get_attachment_image( $attachment_id, 'thumbnail', false, array( 'class' => 'archive-thumbnail' ) );
  if( empty( $first_img ) ){
    $first_img = '<img class="attachment_post_thumbnail" src="' . get_stylesheet_directory_uri() . '/images/no_image.png" alt="No image" />';
  }
  return $first_img;
}

あとはテーマテンプレートの表示したい箇所に以下のような感じで書いてやると、アイキャッチ画像があるときにはアイキャッチ画像を、なければ記事中の一番最初の画像を切り抜きトリミングした状態で表示してくれるはずです。

<?php if( has_post_thumbnail() ): ?>
  <?php echo get_the_post_thumbnail( $post->ID, 'thumbnail', array( 'class' => 'archive-thumbnail' ) ); ?> 
<?php else: ?>
  <?php echo catch_that_image(); ?>
<?php endif; ?>

検証

この記事にアイキャッチ画像は設定していません。以下に3つの画像をアップしていますので、ちゃんと1番目の画像が反映されているかを次のページで確認してみてください。

タグ[アイキャッチ画像]一覧ページ »

image_1 image_2 image_3

ちなみに、1番目のプリチーガールは娘です😆

まとめ

アイキャッチ画像と同じ扱いで記事中の画像を取得することができれば、アーカイブページ等に表示される画像に統一感が出ます。
それだけでも結構洗練されたデザインになるので、クライアントにも喜ばれるのではないでしょうか。