はじめに
投稿で本文に使用された画像を一覧表示したい場合、単純にget_attached_media()を使うだけでは不十分です。
なぜなら、この関数は投稿に直接アップロードされた画像しか取得できず、再利用した画像や他の投稿からの画像は取得できないからです。
そこで今回は、Gutenbergエディターの画像ブロック解析に加え、クラシックエディター(HTML本文)の<img>タグ解析にも対応させた、本文・アイキャッチ・過去の再利用画像まで完全に網羅して一覧表示します。
この記事では、この方法について説明します。
get_attached_media()による画像取得の課題
get_attached_media()を使うと、投稿内で使用されている画像を全て取得できるわけではありません(表1参照)。
| 画像の状況 | get_attached_media() で取得可能か? | 備考 |
|---|---|---|
| 投稿で直接アップロードした画像 | 可能 | post_parentが投稿に紐付いている |
| 投稿Bで投稿Aの画像を再利用 | 不可能 | post_parentは投稿Aのまま |
| 投稿のアイキャッチ画像 | 可能 | アイキャッチも投稿に紐付く場合は取得される |
| ギャラリー内にある画像 | 不可能 | ギャラリーはブロック内の参照であり post_parent に依存しない |
| 外部アップロードした画像(URL指定など) | 不可能 | 投稿に物理的に紐付いていない |
完成イメージ

実装手順
以下の手順で実装します。
- ラベルPHPを追加
以下のコードをfunctions.phpに追加します。
/** * ブロック配列を再帰的に走査して画像ブロックのIDを収集 * * @param array $blocks ブロック構造の配列 * @param array $image_ids 画像IDを保持する参照配列 * @return void */ if (!function_exists('collect_block_image_ids')): function collect_block_image_ids(array $blocks, array &$image_ids) { foreach ($blocks as $block) { if ( isset($block['blockName']) && $block['blockName'] === 'core/image' && !empty($block['attrs']['id']) ) { $image_id = (int) $block['attrs']['id']; if ($image_id > 0) { $image_ids[$image_id] = true; } } // インナーブロックを再帰的に走査 if (!empty($block['innerBlocks']) && is_array($block['innerBlocks'])) { collect_block_image_ids($block['innerBlocks'], $image_ids); } } } endif; /** * 本文HTMLから画像IDを収集 * * @param string $content 本文HTML * @param array $image_ids 画像IDを保持する参照配列 * @return void */ if (!function_exists('collect_content_image_ids')): function collect_content_image_ids(string $content, array &$image_ids) { if (!preg_match_all('/<img\b[^>]*\bsrc=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) { return; } foreach ($matches[1] as $image_url) { $image_id = attachment_url_to_postid($image_url); if ($image_id > 0) { $image_ids[$image_id] = true; } } } endif; // 本文を変更 add_filter('the_content', function ($content) { if (!is_singular('post')) { return $content; } $post_id = get_the_ID(); $eye_catch = true; $image_ids = []; // アイキャッチ画像のIDを取得 if ($eye_catch && has_post_thumbnail($post_id)) { $thumb_id = (int) get_post_thumbnail_id($post_id); if ($thumb_id > 0) { $image_ids[$thumb_id] = true; } } // 本文ブロックを解析して画像ブロックのIDを収集 $blocks = parse_blocks(get_post_field('post_content', $post_id)); collect_block_image_ids($blocks, $image_ids); // クラシック本文から画像IDを収集 collect_content_image_ids(get_post_field('post_content', $post_id), $image_ids); if (empty($image_ids)) { return $content; } // 画像のズーム表示設定を取得 $zoom = get_image_zoom_effect(); ob_start(); ?> <div class="used-images-gallery"> <h2 class="used-images-gallery__title">この記事で使用されている画像</h2> <div class="used-images-gallery__grid"> <?php foreach (array_keys($image_ids) as $id): ?> <?php $full = wp_get_attachment_url($id); $img = wp_get_attachment_image($id, 'medium', false, ['class' => 'used-images-gallery__image']); if (!$full || !$img) { continue; } ?> <figure class="used-images-gallery__item"> <?php if ($zoom !== 'none') : ?> <a href="<?= esc_url($full); ?>" class="used-images-gallery__link"> <?= $img; ?> </a> <?php else : ?> <?= $img; ?> <?php endif; ?> </figure> <?php endforeach; ?> </div> </div> <?php return $content . ob_get_clean(); }); - ラベルCSSを追加
以下のコードをstyle.cssに追加します。
:root { --my-column: 4; } /* 表示幅≦834pxのときは2列に変更 */ @media (width <= 834px) { :root { --my-column: 2; } } .used-images-gallery__grid { display: grid; gap: 15px; grid-template-columns: repeat(var(--my-column), minmax(0, 1fr)); } .used-images-gallery__item img { aspect-ratio: 1 / 1; object-fit: cover; }
WordPress 7.1の「添付画像を使用」機能との違い

WordPress 7.1で追加されたギャラリーの自動追加機能は、該当の投稿に「直接アップロード(添付)されたメディア」(データベース上の post_parent)を判定対象とします(図2参照)。
そのため、本文中に貼り付けていない画像も拾える反面、過去にアップロードした画像を本文で再利用(参照)した場合はギャラリーに含まれません(表1参照)。
一方、本コードは「記事の本文ブロック(parse_blocks)内に実際に設置されている画像」を直接抽出します。アップロード経路に関わらず、記事内で実際に使われている画像だけを正確にギャラリー表示できます。
さいごに
今回紹介した方法を使えば、投稿本文で使用された画像を漏れなく抽出し、本文下に一覧表示することができます。
アイキャッチ画像を含めるかどうかも簡単に切り替えられ、読者に記事内で使用されている画像を視覚的に一覧で示すことができ、記事の利便性や見栄えが向上します。

