wordpress 投稿コンテンツに挿入した画像(メディア)のリンクを抽出する

2014年1月8日

投稿に挿入した画像のリンクをクリックすると Lightbox のような感じで表示するようにしていたが、画像によってはサイズや位置が正しく表示されないことがあったので調べてみた際のメモ。

画像(メディア)の挿入

「メディアを追加」で「添付ファイルの表示設定」の「リンク先」を「メディアファイル」に指定すると画像(メディア)にその画像へのリンクが設定される。

get_posts で画像の情報(URL、高さ、幅)の取得

get_posts のパラメータを以下のように指定すると画像の情報を取得できる。

しかしここに問題があった。

「’post_parent’」を「$post->ID」としているため、他の投稿に対して過去にアップロードした画像を投稿に挿入している場合、その画像の情報は取得できない。そのためサイズの情報が取得できず表示がおかしくなっていた。

<?php    
  $attachments = get_posts( array(
    'post_parent' => $post->ID, 
    'orderby' => 'none',   
    'order' => 'ASC', 
    'post_status' =>  'inherit', 
    'numberposts' => -1, 
    'offset' => 0, 
    'post_type' => 'attachment', 
    'post_mime_type' => 'image',  
   ) );

  if ( $attachments ) {
    foreach ( $attachments as $attachment ) {      
      // $link_image_src にリンク先画像(添付ファイル)の指定したサイズの画像の情報を取得
      $link_image_src = wp_get_attachment_image_src($attachment->ID, 'large'); //'full'と指定すればフルサイズの画像の情報を取得
      echo '<p class="img_link">' .$link_image_src[0] .'</p>';  //URL
      echo '<p class="img_width">' .$link_image_src[1] .'</p>';  //幅
      echo '<p class="img_height">' .$link_image_src[2] .'</p>';  //高さ
      // タイトルを取得
      $title = esc_html(trim($attachment->post_title));  
      if($title) echo '<'.$tag.' class="img_title">' .$title.'</'.$tag.'>';                    
    } 
  }  
?>    

preg_match_all を使って画像の URL を抽出

preg_match_all (pattern, subject, matches, flags, offset )
繰り返し正規表現検索を行う
主なパラメータ
pattern:検索するパターンを表す文字列
subject:入力文字列(検索対象文字列)
matches:マッチしたすべての内容を含む、 flags で指定した形式の多次元配列
戻り値
パターンがマッチした総数を返す(ゼロとなる可能性もある)。 エラーが発生した場合に FALSE を返す。
  • pattern「検索するパターンを表す文字列」に画像の a 要素の正規表現(/wp-content/uploads/を含むリンク)を指定
  • subject「入力文字列(検索対象文字列)」にコンテンツ($mypost->post_content)を指定
  • matches「マッチした内容を含む多次元配列」に $img_array(変数)を指定
  • $img_array[1] には画像の URL (第 1 のキャプチャ用サブパターン)が入る

functions.php に preg_match_all を使って以下のような関数を記述。

function getPostImages($mypost){
  if(empty($mypost)){
    return(null);
  }
  if(preg_match_all('/<a [^>]*"(http:[^">]*\/wp-content\/uploads\/[^">]*)"[^>]*>/u',$mypost->post_content,$img_array)){
    $resultArray = $img_array[1];
  }
  return($resultArray);
}

この方法を使うとコンテンツからいろいろな情報が抽出できそう。但し「echo $post->post_content;」を使うのは危ないらしい。

参考情報:「echo $post->post_content; を避ける3つの理由

getimagesize() を使って画像の幅と高さを取得

getimagesize ( filename, imageinfo )
画像の大きさを取得する
パラメータ
filename:情報を取得したいファイルの名前を指定。ローカルファイルへの参照、あるいは (設定で許可されているなら) ストリームを用いたリモートファイルへの参照を指定。
imageinfo:オプションのパラメータで、 画像ファイルから何らかの拡張情報を引き出すことが可能。
戻り値
最大 7 つの要素からなる配列を返す。
0 番目および 1 番目の要素は、それぞれ画像の幅と高さを表す。
2 番目の要素は IMAGETYPE_XXX 定数のひとつで、 画像の形式を表す。
3 番目の要素は IMG タグで直接利用できる文字列 height=”yyy” width=”xxx” 。
エラー / 例外
もし filename のイメージにアクセスできない場合、 getimagesize() は FALSE を返し、E_WARNING レベルのエラーを発生させる。 読み込み時にエラーが発生した場合は、 getimagesize() は E_NOTICE レベルのエラーを発生させる。
list ( var1 , … )
配列と同様の形式で、複数の変数への代入を行う。 list() は、 単一の操作で一連の変数に値を代入するために使われる。
パラメータ
var1:変数
戻り値
代入した配列を返す

以下をテンプレートのループ内に記述。

  • getPostImages($post) で画像へのリンクの配列を取得
  • getimagesize() に渡すパラメータ「filename」は前後に空白などが含まれているとエラーになる
  • preg_match_all のパターンで空白が含まれないようにしてあるが念のために「trim()」
  • また 以下の形式で getimagesize() に渡すパラメータ「filename」は「”http://….”」のように「”」が付いているとエラーになったので、preg_match_all のパターンで「”」を除いたものにした
<?php 
$postImages = getPostImages($post);

if($postImages != null) {
  echo "<ol>\n";
  for($i = 0; $i<count($postImages);$i++){
    $img_src = trim($postImages[$i]);
     list($width, $height, $type, $attr) = getimagesize($img_src);
     echo '<li><span class="img_src">'. $img_src .'</span> ';
     echo '<span class="img_width">'. $width .'</span> ';
     echo '<span class="img_height">'.$height .'</span></li>'."\n" ; 
  }
  echo "</ol>\n";
}
?>

これで画像の情報が取得できたので、jQuery などでこれを利用できる。