WordPress 投稿時にアイキャッチ画像を自動設定

アイキャッチ画像を設定するのは意外と面倒なんですよね。投稿の最初の画像(添付ファイル)をアイキャッチ画像に自動で設定できれば手間が省けます。

そのためのプラグインもありますが、今回はプラグインを使用しない方法を紹介したいと思います。
元々は、以前作成した既存の投稿のアイキャッチ画像を一括設定するプラグインの「XO Featured Image Tools」プラグインに、この機能を追加するために作成したものです。
それを先行してプラグインを使用しない方法として紹介します。

仕様

  • 投稿時に最初の画像(添付ファイル)をアイキャッチ画像に自動設定する。
  • アイキャッチ画像が既に設定されている場合、アイキャッチ画像を設定(更新)しない。
  • disable_featured_image カスタムフィールドが設定されている場合、アイキャッチ画像を設定しない。

簡易版

この簡易版では、エディタで添付ファイルを追加した画像(img タグ)に、wp-image-{$id} クラスが付加されている場合のみ有効な方法です。

テーマやプラグインによってはこのクラスの出力を抑制しているものもあり、確実にアイキャッチ画像を設定する場合は次セッションの「完全版」を使用してください。

functions.php に下記コードを追加します。

/**
 * 投稿の保存時にコンテンツ内の最初の画像をアイキャッチ画像として保存します。
 *
 * @param int $post_id
 * @param post $post
 * @filter save_post
 */
function save_post_featured_image_lite( $post_id, $post ) {

	if ( wp_is_post_revision( $post_id ) )
		return;

	// disable_featured_image カスタム フィールドが設定されている場合は、アイキャッチ画像を設定しない。
	if ( get_post_meta( $post_id, 'disable_featured_image', true ) )
		return;

	$attachment_id = get_post_meta( $post_id, '_thumbnail_id', true );
	$content = $post->post_content;

	if ( ! $attachment_id ) {
		$attachment_id = 0;
		$matches = array();
		preg_match_all( '/<\s*img .*?src\s*=\s*[\"|\'](.*?)[\"|\'].*?>/i', $content, $matches );
		if ( count( $matches ) ) {
			// wp-image-{$id} クラスより、ID を取得する。
			foreach ( $matches[0] as $key => $img ) {
				$class_matches = array();
				if ( preg_match( '/class\s*=\s*[\"|\'].*?wp-image-([0-9]*).*?[\"|\']/i', $img, $class_matches ) ) {
					$attachment_id = $class_matches[1];
					break;
				}
			}
			if ( $attachment_id ) {
				update_post_meta( $post_id, '_thumbnail_id', $attachment_id );
			}
		}
	}
}

add_action( 'save_post', 'save_post_featured_image_lite', 10, 2 );

完全版

wp-image-{$id} クラスが付加されていない場合でも、画像の URL より添付ファイルの取得を試みて設定する方法です。

functions.php に下記コードを追加します。

※ 簡易版のコードは不要です。

/**
 * 添付ファイルの URL より ID を取得します。
 *
 * @global wpdb $wpdb
 * @param string $url 添付ファイルの URL。
 * @param bool $is_full_size オプション。フルサイズかどうかを示す値。フルサイズの場合は true、別サイズの場合は false。デフォルトは true。
 * @return int 成功した場合は ID(1 以上)を、存在しない場合は 0 を返します。
 */
function get_attachment_id_by_url( $url, $is_full_size = true ) {
	global $wpdb;

	$attachment_id = 0;
	$full_size_url = $url;

	if ( ! $is_full_size ) {
		// URL から、サイズ表記(-999x999)を除去して、フルサイズの URL を取得する。
		$full_size_url = preg_replace( '/(-[0-9]+x[0-9]+)(\.[^.]+){0,1}$/i', '${2}', $url );
		if ( $url === $full_size_url ) {
			// 別サイズではないので中止。
			return $attachment_id;
		}
	}

	$uploads = wp_upload_dir();
	$base_url = $uploads['baseurl'];
	if ( strpos( $full_size_url, $base_url ) === 0 ) {
		//$attached_file = ltrim( $full_size_url, $base_url . '/' );
		$attached_file = str_replace( $base_url . '/', '', $full_size_url );
		$attachment_id = $wpdb->get_var( $wpdb->prepare(
			"SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value='%s' LIMIT 1;",
			$attached_file
		) );
	}

	return (int)$attachment_id;
}

/**
 * 投稿の保存時にコンテンツ内の最初の画像をアイキャッチ画像として保存します。
 *
 * @param int $post_id
 * @param post $post
 * @filter save_post
 */
function save_post_featured_image( $post_id, $post ) {

	if ( wp_is_post_revision( $post_id ) )
		return;

	// disable_featured_image カスタム フィールドが設定されている場合は、アイキャッチ画像を設定しない。
	if ( get_post_meta( $post_id, 'disable_featured_image', true ) )
		return;

	$attachment_id = get_post_meta( $post_id, '_thumbnail_id', true );
	$content = $post->post_content;

	if ( ! $attachment_id ) {
		$attachment_id = 0;
		$matches = array();
		preg_match_all( '/<\s*img .*?src\s*=\s*[\"|\'](.*?)[\"|\'].*?>/i', $content, $matches );
		if ( count( $matches ) ) {
			// wp-image-{$id} クラスより、ID を取得する。
			foreach ( $matches[0] as $key => $img ) {
				$class_matches = array();
				if ( preg_match( '/class\s*=\s*[\"|\'].*?wp-image-([0-9]*).*?[\"|\']/i', $img, $class_matches ) ) {
					$attachment_id = $class_matches[1];
					break;
				}
			}
			// URL より ID を取得する。
			if ( ! $attachment_id ) {
				foreach ( $matches[0] as $key => $img ) {
					$url = $matches[1][$key];
					$attachment_id = get_attachment_id_by_url( $url );
					if ( ! $attachment_id ) {
						$attachment_id = get_attachment_id_by_url( $url, false );
					}
					if ( $attachment_id ) {
						break;
					}
				}
			}
			if ( $attachment_id ) {
				update_post_meta( $post_id, '_thumbnail_id', $attachment_id );
			}
		}
	}
}

add_action( 'save_post', 'save_post_featured_image', 10, 2 );

最後に

XO Featured Image Tools プラグインに、この機能を追加したバージョンを近いうちに公開したいと思っています。

機能的には、あの(どの?)プラグインと殆ど機能が被ってしまうことになってしまいましたが、添付ファイルの取得方法や一括設定等は全く異なるアプローチをとっているので意味はあるのかなと思っています。

売りは一括設定が高速なところでしょうか。あの(だからどの?)プラグインが動作しない場合等はお試しください。

コメント

  • 初めまして。
    Wordpress初心者で、勉強の一環でアンテナサイトの作成をしている30代会社員です。
    ご紹介いただいた「XO Featured Image Tools」をインストールしてアイキャッチ画像の生成を試みましたが生成できませんでした。
    実は「Auto post thumbnail」でできず、さまよっていた中でこちらのブログにたどり着き拝見させていただきました。
    原因がわからず困り果てているのですが、もし、もしよろしければなにかアドバイスをいただくことはできませんでしょうか。。
    突然の図々しいコメントで大変恐縮ではございますが、何卒宜しくお願い致します。

    なお、アンテナサイトとして取得している記事は【らばQ】【ロケットニュース24】で、そのうち【ロケットニュース24】のアイキャッチ画像のみ生成ができていない状況です。

    • こんにちは、初めまして。
      「XO Featured Image Tools」プラグインは、記事(コンテンツ)内の最初の画像を対象とします。RSS のサムネイルには対応していません。
      記事内に画像はありますか?

コメントを残す

メールアドレスが公開されることはありません。

日本語でコメントを入力してください。(スパム対策)