トイレのうず

WordPressで外部サーバーの画像をアイキャッチ画像として表示する

当記事はアフィリエイト広告を掲載しています。

このサイトは画像を Picasa ウェブアルバムに置いています。理由はレンタルサーバーの負荷を減らすためと、ドメインを分散させることで表示を速くさせるための 2 つです。
→ Picasa に置いた画像を WordPress で利用する

しかし困ったことがあります。 WordPress のアイキャッチ機能では外部サイトに置いた画像を指定することができないのです。外部サイトに置いた画像をアイキャッチとして使うため function.php にコードを書いたのでその備忘録です。

WordPress のアイキャッチ画像で外部 URL が指定できないわけ

WordPress 純正のアイキャッチ画像はメディアライブラリで管理している画像しか指定できません。記事の 1 枚目の画像を自動でアイキャッチに指定してくれる「 Auto Post Thumbnail 」というプラグインもあるのですが、結局外部から画像を自分のサーバーに読み込んで、それをアイキャッチに設定し表示しているだけなのです。それじゃあ、せっかく画像を外部サーバーに置いているのにメリットがありません。 Picasa や Flickr は画像を保存するだけで、何種類かのサイズでサムネイルを自動的に作成してくれるので、それを利用しない手はないからです。

どうして外部サーバーに置いた画像を指定できないかというと、 WordPress のデータの持ち方に理由があります。アイキャッチの設定はカスタムフィールドを保存するのと同じ postmeta テーブルに保存され、「ユニークキー」「投稿 ID 」「 _thumbnail_id 」「画像 id 」という形で保存されています。「画像 id 」とは posts テーブルで管理してい画像の id です。 WordPress は投稿やページなどのコンテンツとメディアライブラリでアップグレードした画像を同じテーブルで管理しているのです。「 _thumbnail_id 」は名前の通り id しか処理することができないのです。ちなみに「 _thumbnail_id 」の頭の「 _ (アンダーバー)」は不可視の意味で、カスタムフィールドには表示されません。

外部サーバーの画像をアイキャッチとして使う方法を調べてみた

外部サーバーに画像を置いている場合、投稿の中身を読み込んで img タグを探してその URL を取得する方法しかないことがわかりました。
→ memocarilog : WordPress の投稿記事内の画像の最初の 1 枚をサムネイルとして表示する方法

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 = "/images/default.jpg";
  }
  return $first_img;
}

表示したい箇所に以下を書く。

<img src="<?php echo catch_that_image(); ?>" alt="" width="" height="" />; ?>

このコードで動かして問題が 3 つ出てきました。

  1. アフィリエイトの表示カウント用の 1px 四方の画像も拾ってくる。
  2. img タグの終わりで改行されていないと画像が表示されない。
  3. アイキャッチ画像を表示するたびに、表示件数分の記事を読み込みそれを処理している。(サーバーに負担がかかる。)

問題 1 は対象画像からアフィリエイト関係を除外すれば対応できます。

問題 2 は正規表現が間違っているので 6 行目を下記のように書き換えれば OK です。正規表現の「 ? 」が足りないだけです。

$output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*?>/i', $post->post_content, $matches);

問題 3 は上記コードで取得した投稿の最初の画像 URL をカスタムフィールドに保存することで解決することにしました。

WordPress で Picasa の画像をアイキャッチに使用するコード

上記 3 つの問題を解決してたコードが下記です。このサイト用なので、利用するときは適宜手を加えてください。

動作は下記のよう。

  • 投稿や更新時にアイキャッチが設定されていなかったら、 Picasa のサムネイルサイズ( s160-c )をカスタムフィールド「 thumbnail_url 」に設定する。
  • カスタムフィールドを読み込みアイキャッチとして表示。
  • アイキャッチが設定してなかった場合、カテゴリ別にデフォルトのアイキャッチを表示。

また 45 行目のコメントを外すと、アイキャッチ表示時にもアイキャッチ URL がカスタムフィールドへ保存されます。コメントを外して動作させることで、アイキャッチがあるページをブラウザから表示させると、アイキャッチを設定していない記事のカスタムフィールドへアイキャッチ画像の URL を保存することができます。アイキャッチを設定する手間が少し省けます。(ひと通りアイキャッチが設定できたら、再度コメントアウトしてください。コメントアウトしないと、アイキャッチが設定されていない場合、記事をすべて読み込み再度処理を行うことになります。)

function.php に追加。

//投稿時にアイキャッチを設定する
add_action('publish_post', 'my_post_thumbnail_url');
function my_post_thumbnail_url($post_id){
	//カスタムフィールドに設定してあるアイキャッチURL取得
	$first_img = get_post_meta($post_id, 'thumbnail_url', true);
	set_my_post_thumbnail_url($post_id, $first_img);
}

//記事の最初の画像をアイキャッチに指定
function set_my_post_thumbnail_url($post_id, $first_img){
	//カスタムフィールドが空、またはpicasa以外だったら下記の処理
	if(empty($first_img) || (strpos($first_img, '1010uzu.com') || strpos($first_img, 'mzstatic.com')) !== false){
		$post = get_post($post_id);
		ob_start();
		ob_end_clean();
		preg_match_all('/<img.+?src=[\'"]([^\'"]+)?[\'"].*?>/i', $post->post_content, $matches);
		foreach( $matches [1] as $value ){
			if( preg_match("/(lh\d\.ggpht\.com)|(lh\d\.googleusercontent\.com)|(1010uzu\.com)|(a\d\.mzstatic\.com)/", $value) ){
				$first_img = $value;
				break; 
			}
		}
    
    	//カスタムフィールドにアイキャッチURLを追加
    	if((strpos($first_img, 'ggpht') || strpos($first_img, 'googleusercontent')) !== false){
	     	$first_img = preg_replace('/\/(w|s|h)(\d+)\//', '/s160-c/', $first_img);
    	}
    	//アイキャッチが設定されていないときは追加、それ以外は更新。
    	if(!empty($first_img)){
    		if ( !add_post_meta($post->ID, 'thumbnail_url', $first_img, true) ) update_post_meta($post->ID, 'thumbnail_url', $first_img);
    	}
	}
	return $first_img;
}

//記事の最初の画像をサムネイルで表示(picasaの画像)
function my_post_thumbnail() {
	if( null === $post_id ){
		$post_id = get_the_ID();
	}
	
	//カスタムフィールドに設定してあるアイキャッチURL取得
	$first_img = get_post_meta($post_id, 'thumbnail_url', true);
	//カスタムフィールドが空だったらアイキャッチをセット(通常はコメントアウト)
	//$first_img = set_my_post_thumbnail_url($post->ID, $first_img);

	//デフォルトイメージ設定
	if(empty($first_img)){
		$first_img = "https://lh4.ggpht.com/-pucHCWSTV70/UAxF6phd2nI/AAAAAAABJrs/ImQqhltuBKY/s160-c/boyaki.jpg";
		//カテゴリー別デフォルトイメージ設定
		if ( in_category('suidou') || in_category('%e3%81%a9%e3%81%86%e3%81%a7%e3%81%97%e3%82%87%e3%81%86%e3%83%aa%e3%82%bf%e3%83%bc%e3%83%b3%e3%82%ba') || in_category('jungle-revenge') || in_category('new-work') || in_category('classic')) {
			$first_img = "https://lh5.ggpht.com/-PrYnn5YW2Do/UAxF7nGyPaI/AAAAAAABJsA/m3b7JGK9qk8/s160-c/suidou.jpg";
		} elseif ( in_category('mac') ) {
			$first_img = "https://lh3.ggpht.com/-g5oMqYaGk-E/UAxF7kTEpbI/AAAAAAABJr0/LNDRDczmyOM/s160-c/mac.jpg";
		} elseif ( in_category('antenna-dtb') ) {
			$first_img = "https://lh3.ggpht.com/-D4-xrb5rOhY/UAxF6awBhuI/AAAAAAABJrg/4gnxv9Nl_VU/s160-c/antenna-dtb.jpg";
		} elseif ( in_category('digital-items') ) {
			$first_img = "https://lh5.ggpht.com/-_DJl_pU51cI/UAxIc_mNkDI/AAAAAAABJtE/ICUZixJOdls/s160-c/digital-items.jpg";
		} elseif ( in_category('web-internet') ) {
			$first_img = "https://lh4.ggpht.com/-2J3iysuwMi0/UAxF8FX7-_I/AAAAAAABJsY/lZ5Xe2cCMvg/s160-c/web-internet.jpg";
		} elseif ( in_category('wordpress') ) {
			$first_img = "https://lh5.ggpht.com/-vv1g34FjCPI/UAxF8B3gy7I/AAAAAAABJsQ/78Jfg-bGLt8/s160-c/wordpress.jpg";
        	
		} elseif ( in_category('entertainment') || in_category('cue') || in_category('music-entertainment') || in_category('ohizumiyo') || in_category('mister') ) {
			$first_img = "https://lh4.ggpht.com/-X6MkrwHnwfA/UAxIc6rMhbI/AAAAAAABJtI/PlKqubjmOUo/s160-c/entertainment.jpg";
		} elseif ( in_category('f1') ) {
			$first_img = "https://lh3.ggpht.com/-mk6Ysvbn9Xc/UEdW4wowfnI/AAAAAAABLQU/Eu-X9vWbpZI/s160-c/f1.png";
		} elseif ( in_category('life') ) {
			$first_img = "https://lh5.ggpht.com/-jxKancXTzU0/UAxF7tvSYqI/AAAAAAABJr4/DNxcxursm8M/s160-c/life.jpg";
		} elseif ( in_category('topics') ) {
			$first_img = "https://lh4.ggpht.com/-J7R2GUFv0jU/UAxF76XcWoI/AAAAAAABJsI/pCoObDM7YPU/s160-c/topics.jpg";
		} elseif ( in_category('boyaki') ) {
			$first_img = "https://lh4.ggpht.com/-pucHCWSTV70/UAxF6phd2nI/AAAAAAABJrs/ImQqhltuBKY/s160-c/boyaki.jpg";
		} elseif ( in_category('information') ) {
			$first_img = "https://lh6.ggpht.com/-H5B16rBDZP8/UAxF6UjYPCI/AAAAAAABJrk/ClqEmpAjMWw/s160-c/information.jpg";
		}
	}
	echo '<img width="160" height="160" src="' . $first_img . '" class="attachment-thumbnail" alt="thumbnail" />';
}

表示するときは下記のように記述します。 WordPress のテンプレートタグ「 the_post_thumbnail() 」と同じような HTML が出力されます。

<?php my_post_thumbnail(); ?>

Picasa についての補足説明

ggpht.com 、 googleusercontent.com は Picasa ウェブアルバムに保存してある画像のドメインです。

s160-c は 160 px の正方形に切り抜かれた画像という意味です。

Picasa では下記のサイズのサムネイルが元から用意されています。
→ Google Developers : Picasa Web Albums query parameters reference

クロップした(正方形に切り抜いた)画像のサムネイル
32, 48, 64, 72, 104, 144, 150, 160

クロップなしのサムネイル
94, 110, 128, 200, 220, 288, 320, 400, 512, 576, 640, 720, 800, 912, 1024, 1152, 1280, 1440, 1600

これ以外の数値を指定しても画像はその大きさで表示されます。

パラメーターの使い方は下記を参照。
→ mattintosh note : Picasa ウェブアルバムのサムネイルカスタマイズのまとめ

Picasa が Google+ に吸収されつつあるのが少し不安ではありますが、現時点では Picasa が画像置き場として使いやすいです。

関連記事

外部サイトの画像を WordPress のサイトアイコンに設定する
WordPress
ブログカードのサイトアイコンがWordPressのデフォルト
Picasa に置いた画像を WordPress で利用する
WordPressWebサービス
thumbnail
WordPress の Simple GA Ranking でカテゴリ別の人気記事をウィジェットに表示する
WordPress
人気記事一覧にアイキャッチを表示
Picasa and Google Plus Express で画像の挿入ができなくなった
WordPress
thumbnail
WordPress 外部リンクを表示しれくれるプラグイン【 Link Indication Plugin 】
WordPress
thumbnail
WordPress 高速化メモ
WordPress
Google Analytics:サイトの速度の提案