私がWordPressサイトを作る時によく使っている独自の処理に「特定の投稿に関連する画像をすべて取得する」という関数がある。指定した投稿に設定されているサムネイル(アイキャッチ)画像、添付ファイルとしての画像、直接記事内に貼り付けた画像を一括で取得してくれる関数だ。

例えば、記事一覧などのアーカイブコンテンツを作成する際に、該当記事に画像が含まれていればそれをサムネイルとして表示させたり、独自のギャラリーを作成する時などに利用できる。

毎度サイト作る時に、以前作ったテーマからこの関数を引っ張り出して再利用していたのだが、面倒なので、ここにTIPSとしてナレッジ化しておこうかと思う。

/**
 * Retrieve all images that used in specific post.
 *
 *
 * @param int $post_id [optional] The current post ID in the loop is if you do not specify.
 * @param string $image_type [optional] When you want to specify the image type.
 * @return mixed If no image is false
 */
function retrieve_images_in_post( $post_id=null, $image_type=null ) {
  $image_count = 0;
  $images = [
    'thumbnails' => [], 
    'attachments' => [], 
    'embeds' => []
  ];

  // Initialize by dynamically allocating an argument
  $arguments = func_get_args();
  if (array_key_exists(strtolower(end($arguments)), $images)) {
    $image_type = array_pop($arguments);
  } else {
    $image_type = null;
  }
  $post_id = isset($arguments[0]) && intval($arguments[0]) > 0 ? intval($arguments[0]) : null;

  if (empty($post_id)) {
    global $wp_query;
    $_post = $wp_query->post;
    $post_id = isset($_post->ID) ? $_post->ID : false;
    if (!$post_id) 
      return false;
  }

  $post = get_post($post_id);
  if (empty($post)) 
    return false;

  // Retrieve the post thumbnails
  if (has_post_thumbnail($post_id)) {
    $thumbnail_id = get_post_thumbnail_id($post_id);
    $thumbnail = get_post($thumbnail_id);
    if (file_exists($thumbnail->guid)) {
      $images['thumbnails'][] = $thumbnail->guid;
    } else {
      $_parse_url = preg_replace('/^https?:\/\//iU', '', $thumbnail->guid);
      $_path = explode('/', $_parse_url);
      unset($_path[0]);
      $_relative_path = '/' . implode('/', $_path);
      if (file_exists(ABSPATH . $_relative_path)) 
        $images['thumbnails'][] = $_relative_path;
    }
  }

  // Retrieve the attachment images
  $attachments = get_posts( array('post_parent'=>$post_id, 'post_type'=>'attachment', 'posts_per_page'=>-1, 'post_status'=>'any') );
  if (!empty($attachments)) {
    foreach ($attachments as $_item) {
      if (strpos($_item->post_mime_type, 'image/') !== false) {
        if (file_exists($_item->guid)) {
          $images['attachments'][] = $_item->guid;
        } else {
          $_parse_url = preg_replace('/^https?:\/\//iU', '', $_item->guid);
          $_path = explode('/', $_parse_url);
          unset($_path[0]);
          $_relative_path = '/' . implode('/', $_path);
          if (file_exists(ABSPATH . $_relative_path)) 
            $images['attachments'][] = $_relative_path;
        }
      }
    }
    $images['attachments'] = array_unique($images['attachments']);
  }

  // Retrieve the embedded images
  if (preg_match_all('/<img.*src=(|["\'])(.*)\1*[^>]*>/iU', $post->post_content, $matches) && is_array($matches) && array_key_exists(0, $matches)) {
    foreach ($matches[0] as $candidate) {
      if (preg_match('/(?<!_)src=([\'"])?(.*?)\\1/i', $candidate, $matches) && is_array($matches) && array_key_exists(2, $matches)) {
        $image_path = $matches[2];
      } else
      if (preg_match('/(?<!_)src=\s?(.*?)\s*([^>]*)>/i', $candidate, $matches)) {
        $image_path = strstr($matches[2], ' ', true);
      }
      if (isset($image_path) && !empty($image_path)) {
        if (strpos( $image_path, 'http' ) === false) {
          $images['embeds'][] = file_exists(ABSPATH . $image_path) ? site_url($image_path) : $image_path;
        } else {
          $images['embeds'][] = $image_path;
        }
      }
    }
    $images['embeds'] = array_unique($images['embeds']);
  }

  foreach ($images as $_type => $_images) {
    $_count = count($_images);
    if (!empty($image_type) && $_type === $image_type) {
      return $_count > 0 ? $_images : false;
    }
    $image_count += $_count;
  }

  return $image_count === 0 ? false : $images;

}

使い方は、テーマのfunctions.phpなどテンプレート内にて、

$images = retrieve_images_in_post();
var_dump($images);
/*
array(3) { 
  ["thumbnails"]=> array(1) { 
    [0]=> string(37) "/wp-content/uploads/2015/09/thumbnail.jpg" 
  } 
  ["attachments"]=> array(1) { 
    [0]=> string(38) "/wp-content/uploads/2015/09/attachment.jpg" 
  } 
  ["embeds"]=> array(3) { 
    [0]=> string(62) "http://ka2.org/wp-content/uploads/2015/09/sample-1.jpg" 
    [1]=> string(53) "http://l-tool.net/tools/cart/0303/free/img/sample.jpg" 
    [2]=> string(66) "http://ka2.org/wp-content/uploads/2015/09/android_and_html5.png" 
  } 
}
*/

──として使う。画像が取得できた場合、戻り値として画像種別ごとの画像パスの配列が返ってくる。もし投稿に画像がない場合は真偽値のfalseが返る。

取得できる画像の種別としては、

  • thumbnails ─ 投稿に設定されているアイキャッチ画像
  • attachments ─ 投稿に貼り付けられたメディアのうち添付ファイルの形式が画像のもの
  • embeds ─ 投稿に<img>タグで貼り付けられたすべての画像(外部サイトの画像も含む)

──となっている。

また、引数として特定の投稿IDや、取得したい画像種別を指定できる。

例えば、投稿IDが154番の投稿から画像を取得したい場合:

$images = retrieve_images_in_post(154);

また、画像種別thumbnailsのみを取得対象にしたい場合:

$images = retrieve_images_in_post('thumbnails');

さらに複合条件も指定可能:

$images = retrieve_images_in_post(154, 'thumbnails');

何気にこの関数、結構重宝するので、もしよかったら使ってみてください。

久々、WordPressの小ネタでした。