Help us understand the problem. What is going on with this article?

【WordPress】記事内の最初の画像をサムネイルとして取得する方法【全サイズ・srcset&sizes対応版】

More than 1 year has passed since last update.

投稿内の最初の画像をアイキャッチにする

WordPressの記事一覧などで『アイキャッチ画像が設定されていればそれを取得し、設定されていなければ投稿内の最初の画像を取得』する方法は、調べればすぐ出てくる。

 → WordPressで記事内の最初の画像をアイキャッチ代わりに使う方法

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

function.php
function catch_that_image() {
    global $post, $posts;
    $first_img = '';
    ob_start();
    ob_end_clean();
    $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
    $first_img = $matches [1] [0];

if(empty($first_img)){ //Defines a default image
        $first_img = "http://detarame.moo.jp/wp/wp-content/themes/whbk5/images/default.jpg";
    }
    return $first_img;
}
example.php
<?php if (has_post_thumbnail()) : ?>
    <?php the_post_thumbnail('thumbnail'); ?>
<?php else : ?>
    <img src="<?php echo catch_that_image(); ?>" alt="<?php the_title(); ?>" />
<?php endif ; ?>

しかし、このやり方では投稿内の画像サイズの設定もそのまま反映されてしまうため、サイズ設定の指定や出し分けができない上に、レスポンシブにきちんと対応できないのが一番の難点。

「CSSでwidthheightをパーセント指定にしたら?」と言われるかもしれないところだが、
自分のブログならそれでもいいが成果物としてクライアントに納品する場合、投稿内の画像のサイズ設定や元サイズなんて指定できないため、
幅が100~200px程度のアイコンのような画像が投稿内の最初の画像だった場合、width: 100%;とかにしてると、画像が酷くぼやけて見えてしまう。
CSSでの表示はmax-widthの指定のみにとどめ、wp_get_attachment_imageを使ってサイズを指定し、さらにsrcsetsizesでデバイスごとに適切に表示画像を出し分けたい。

そのためには、

  1. 投稿内の画像から画像IDを取得
  2. wp_get_attachment_imageで出力
  3. srcsetsizesを指定する

という手順を踏んで出力する必要がある。

投稿内の画像からIDを取得

投稿ビジュアルエディタで、メディアライブラリから画像を挿入した場合、以下のコードになる。

<img class="wp-image-*** size-(画像サイズ)" src="(画像url)" alt="***" width="***" height="***" />

wp-image-***というクラスが付与されるが、***部分がIDなので、それを引っ張ってくればよい。

preg_match_all( '/<img.+class=[\'"].*wp-image-([0-9]+).*[\'"].*>/i', $post->post_content, $matches );

これで、投稿内の画像IDを$matchesで取得できる。

srcsetsizesを指定

srcsetsizesは、WordPress4.0以降ならそれぞれwp_get_attachment_image_srcsetwp_get_attachment_image_sizesという関数が用意されているので、それを使う。

wp_get_attachment_image_srcset() | Function | WordPress Developer Resources

wp_get_attachment_image_sizes() | Function | WordPress Developer Resources

この関数、なぜか日本語の情報が異常に少なく(それどころか日本語記事だとsrcsetとsizesを削除する方法ばっかり出てくる)、日本語訳のリファレンスすらない。
投稿画像をテーマ内で呼び出してかつレスポンシブ対応させる場合は、ほとんど必須と言ってもいいと思うのだけど…

wp_get_attachment_image_srcsetwp_get_attachment_image_sizes

どちらも( $attachment_id, $size, $image_meta )の3つの引数を取る。
リファレンスによると以下の通り。

パラメータ 説明 初期値
$id 画像のID (なし)
$size 画像のサイズ。
'medium'などの登録されている画像サイズ
add_image_sizeで追加したものも含む)か、
幅と高さの数値の配列(単位はpxになる)のどちらか。
'medium'
$image_meta wp_get_attachment_metadata()で返される
画像のメタ情報。…らしい。
null

基本的には、IDと画像サイズを指定すれば、それに対応したsrcsetsizes)の値を出力してくれる、という認識でよい。
$image_metaが正直かなり謎で、コードを追う限り実際の返り値には一切影響していないように見えるため全く必要なさそうなんだが、一体何なんだろうか……今回のコードではnullのままでも問題なく動作したので説明を省くことにする。

で、wp_get_attachment_imageなら属性値を好きに追加することができるので、
上記関数で取得した値をそれぞれ配列で指定してあげればOK。

実際に出力

function.phpに、下記を追記する。

function.php
// $get_size: 取得する画像のサイズ
// $altimg_id: 代替画像のID。(画像はあらかじめメディアライブラリからアップロードしておく)
//             nullの場合、投稿内に画像が無ければ何も出力しない
function catch_thumbnail_image($get_size = 'thumbnail', $altimg_id = null) {
    global $post;
    $image = '';
    $image_get = preg_match_all( '/<img.+class=[\'"].*wp-image-([0-9]+).*[\'"].*>/i', $post->post_content, $matches );
    $image_id = $matches[1][0];
    if( !$image_id && $altimg_id ){
        $image_id = $altimg_id;
    }
    $image = wp_get_attachment_image( $image_id, $get_size, false, array(
        'class' => 'thumbnail-image',
        'srcset' => wp_get_attachment_image_srcset( $image_id, $get_size ),
        'sizes' => wp_get_attachment_image_sizes( $image_id, $get_size )
    ) );
    if( empty($image) ) {
        $image = '';
    }
    return $image;
}

出力したい場所に以下のコードを挿入。

example.php
<?php
$catch_thumbnail_size = 'thumbnail';
if(has_post_thumbnail()){
    the_post_thumbnail($catch_thumbnail_size);
} else {
    echo catch_thumbnail_image($catch_thumbnail_size);
}
?>

これで、

  1. アイキャッチ画像が設定してある場合はそれを取得し出力
  2. アイキャッチは無いが投稿内に画像がある場合は、そのうちの1番最初の画像を取得し出力
  3. それも無い場合は代替画像を出力 or 何もしない

という動作を

  • 投稿内画像のサイズ設定に影響されない
  • 自由に出力サイズを指定
  • srcsetsizesも出力し、デバイスサイズに合わせた画像を表示させる

という条件で実現できる。

ryujisanagi
しがない副業コーダー。 主に企業のコーポレートサイト、LPなどの制作。ただし副業。 なのでqiitaへの投稿はHTML・CSS・JS・PHPがメイン。特にWordPressに関するもの多め。 主に備忘録として使用していますが、同じネタで困った人の助けになれば。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした