Unsplash APIを使ってタイトルからアイキャッチを自動的に設定する


Bing AI Chatは「上限なのでまた明日!」を表示してから24時間経過しても相変わらず駄目。暇つぶしに地味だったこのサイトにアイキャッチを設定することにした。とは言え真面目に写真を選んでアップロードするのも面倒。Unsplash APIを使って自動生成することに。

タイトルからそれらしい画像を探し、アイキャッチに設定する機能、プラグインがあればそれでも良かったが、自動検索/設定するものが無く(あっても有償)、作ってしまった…的な感じだ。

APIを使うにはAPI Keyが必要なので、Unsplashサイトでアカウントを作り、API Keyを取得する(無償)。後はfunctions.phpのフック方法などをChatGPTに聞きつつコードを書いた。以下、全文。API Keyの部分だけ書き換えれば動くはずだ。

// WordPressのアイキャッチをUnsplashからタイトルで検索して自動的に設定

require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');

function set_post_thumbnail_from_unsplash($post_id) {
    $post = get_post($post_id);
    if (!has_post_thumbnail($post_id) && $post->post_type == 'post' && $post->post_status == 'publish') {

        // Unsplash APIのパラメータ設定
        $query_args = array(
            'query' => $post->post_title,
            'per_page' => 1,
            'orientation' => 'landscape',
            'client_id' => 'ここへAPI Keyを入れる',
            'w' => 1024,
            'h' => 768
        );

        // Unsplash API
        $url = 'https://api.unsplash.com/search/photos?' . http_build_query($query_args);
        $response = wp_remote_get($url);

        // responseでエラーが無ければ処理
        if (is_array($response) && !is_wp_error($response)) {
            $json = wp_remote_retrieve_body($response);
            $data = json_decode($json, true);
            if (isset($data['results'][0]['urls']['regular'])) {

                // 得られたurlの?crop以降を消す
                $longurl = $data['results'][0]['urls']['regular'];
                $pos = strpos($longurl, '?crop');
                if ($pos !== false)
                    $url = substr($longurl, 0, $pos);

                // urlの最後に?ext=.jpgを付けないと無効のイメージとなる
                $attachment_id = media_sideload_image($url .'?ext=.jpg', $post_id, $post->post_title, 'id');
                if (is_wp_error($attachment_id)) {
                    // wp-config.phpを書き換える
                    //  define('WP_DEBUG', true);
                    //  if (WP_DEBUG)
	            //      define('WP_DEBUG_LOG', true); // wp-content/debug.logを出力
                    error_log($post->post_title);
                    error_log($url);
                    error_log(print_r($attachment_id->get_error_messages(), true));
                } else
                    set_post_thumbnail($post_id, $attachment_id);
            }
        }
    }
}
/*
 アイキャッチ画像のアスペクト比を合わす。Twenty Twenty-Three用
 .home .wp-block-post-featured-image img,
 .search .wp-block-post-featured-image img,
 .archive .wp-block-post-featured-image img {
	width:700px;
	height:150px;
	object-fit:cover;
	object-position: center center;
  }
  .single .wp-block-post-featured-image img {
	width:100%;
	height:300px;
	object-fit:cover;
	object-position: center center;
 }
*/
add_action('save_post', 'set_post_thumbnail_from_unsplash');

ここで一箇所ハマったのが、media_sideload_image()に渡すURL。APIから得たURLは?&が混ざった非常に長いもので、しかも拡張子無し。この関係でメディアにうまく登録できず、ご覧のような細工をした。この場合、フルサイズの画像を拾ってくるが、自動的にリサイズした画像も何本か出来るので表示上の問題は無い。

最後のCSSは、queryで画像サイズとアスペクト比を指定しても、結局その通りは取れず仕方なくCSSで合わすようにしている。

実際自動設定された写真を眺めていると、あまりタイトルとは関係無い気がしなくもないが、同じタイトルだと同じ画像を取得するので一応合っているのだろう。これもAIの一種と言うことで(笑)

by 人間