アイキャッチ画像のリンク設定

アイキャッチ画像リンク設定サムネ

制作概要

WordPressの標準機能では記事ページのアイキャッチ画像に任意のリンク先を設定できないため、独自のリンク設定機能を実装しました。

エディターの投稿編集画面にリンク先URLの入力欄を追加し、記事ごとにリンク先を設定できる仕組みを構築しています。

また、リンクが設定された画像には意図しないページ遷移を防ぐため「View Site」と外部リンクアイコンを表示し、リンク先があることを視覚的に伝えるようにしました。

実装内容

1.投稿編集画面にURL入力欄を追加(エディター側のJs)

編集画面の投稿タブ内に設定パネルを追加し、リンク先URLを入力・更新できるようにしています。入力欄には現在の設定値を表示し、URLが入力されている場合はリンク先を確認できるリンクも表示します。

featured-image-link-editor.js
(function (wp) {

    /* ----------------------------------------
       使用するWordPressの機能
    ---------------------------------------- */

    const { registerPlugin } = wp.plugins;
    const { PluginDocumentSettingPanel } = wp.editPost;
    const { TextControl, ExternalLink } = wp.components;
    const { createElement: el } = wp.element;
    const { useSelect, useDispatch } = wp.data;

    /* ----------------------------------------
       アイキャッチ画像リンク設定パネル
    ---------------------------------------- */

    function FeaturedImageLinkPanel() {

        // 投稿に保存されているメタデータを取得
        const meta = useSelect(function (select) {
            return (
                select('core/editor').getEditedPostAttribute('meta') || {}
            );
        }, []);

        // 投稿内容を更新する機能
        const { editPost } = useDispatch('core/editor');

        // 現在設定されているURL
        const url = meta._atsu_featured_image_link || '';

        /* URLの更新 */
        function updateUrl(value) {

            editPost({
                meta: {
                    ...meta,
                    _atsu_featured_image_link: value,
                },
            });
        }

        /* ----------------------------------------
           パネルの表示
        ---------------------------------------- */

        return el(
            PluginDocumentSettingPanel,
            {
                name: 'atsu-featured-image-link',
                title: 'アイキャッチ画像リンク',
                className: 'atsu-featured-image-link-panel',
            },

            // URL入力欄
            el(TextControl, {
                label: 'リンク先URL',
                type: 'url',
                value: url,
                placeholder: 'https://example.com/',
                help: '未入力の場合はリンクを設定しません。',
                onChange: updateUrl,
            }),

            // URLが入力されている場合のみ確認リンクを表示
            url
                ? el(
                    'p',
                    {},
                    el(
                        ExternalLink,
                        {
                            href: url,
                        },
                        'リンク先を確認する'
                    )
                )
                : null
        );
    }

    /* ----------------------------------------
       プラグイン登録
    ---------------------------------------- */
    registerPlugin(
        'atsu-featured-image-link',
        {
            render: FeaturedImageLinkPanel,
        }
    );
})(window.wp);

PluginDocumentSettingPanel を使用して投稿編集画面に設定パネルを追加し、TextControl でリンク先URLの入力欄を作成しています。

URL追加部分

入力欄には投稿に設定されているURLを表示し、変更した内容を投稿の編集データに反映します。またURLが入力されている場合はリンク先を確認できるリンクを表示し、未入力の場合は表示しないようにしています。

2. URLの保存とアイキャッチ画像へのリンク設定(PHP)

入力したURLを投稿のメタデータとして保存できるように設定し、公開ページのアイキャッチ画像にリンク先を反映する処理を実装しました。

featured-image-link.php
<?php
/* ----------------------------------------
   アイキャッチ画像リンク設定
---------------------------------------- */

/* カスタムフィールドの登録 */

function AtsuPortfolioTheme_register_featured_image_link_meta() {

    // 投稿タイプにカスタムフィールドを追加
    add_post_type_support( 'post', 'custom-fields' );

    // REST API経由でメタデータを利用できるようにする
    register_post_meta(
        'post',
        '_atsu_featured_image_link',
        array(
            'type'              => 'string',
            'single'            => true,
            'default'           => '',
            'show_in_rest'      => true,
            'sanitize_callback' => 'esc_url_raw',
            'auth_callback'     => function() {
                return current_user_can( 'edit_posts' );
            },
        )
    );
}
add_action(
    'init',
    'AtsuPortfolioTheme_register_featured_image_link_meta'
);

/* ----------------------------------------
   個別記事のアイキャッチ画像にリンクを追加
---------------------------------------- */
function AtsuPortfolioTheme_render_featured_image_link(
    $block_content,
    $block
) {

    // 個別投稿ページ以外では処理しない
    if ( ! is_singular( 'post' ) ) {
        return $block_content;
    }

    // 投稿のアイキャッチ画像ブロック以外は処理しない
    if (
        $block['blockName'] !== 'core/post-featured-image'
    ) {
        return $block_content;
    }

    // 現在の記事IDを取得
    $post_id = get_queried_object_id();

    if ( ! $post_id ) {
        return $block_content;
    }

    // 現在処理している投稿が、個別記事の投稿自身でない場合は処理しない
    if ( get_the_ID() !== $post_id ) {
        return $block_content;
    }

    // リンク先URLを取得
    $url = get_post_meta(
        $post_id,
        '_atsu_featured_image_link',
        true
    );

    // URLが未設定なら通常表示
    if ( empty( $url ) ) {
        return $block_content;
    }

    // アイキャッチ画像が設定されていない場合は通常表示
    if ( ! has_post_thumbnail( $post_id ) ) {
        return $block_content;
    }

    // デフォルト画像の場合はリンク処理しない
    if ( strpos( $block_content, 'is-default-thumbnail' ) !== false ) {
        return $block_content;
    }

    // figureタグの内側にリンクを追加
    return preg_replace_callback(
        '/(<figure\b[^>]*>)(.*?)(<\/figure>)/s',
        function ( $matches ) use ( $url ) {

            // figureタグにクラスを追加
            $figure = preg_replace(
                '/<figure\b/',
                '<figure class="wp-block-post-featured-image"',
                $matches[1],
                1
            );

            return sprintf(
                '%1$s<a href="%2$s" target="_blank" rel="noopener noreferrer">%3$s</a>%4$s',
                $figure,
                esc_url( $url ),
                $matches[2],
                $matches[3]
            );

        },
        $block_content,
        1
    );
}
add_filter(
    'render_block',
    'AtsuPortfolioTheme_render_featured_image_link',
    10,
    2
);

register_post_metaを使用して、リンク先URLを投稿のメタデータとして扱えるようにしています。また、REST APIから利用できるように設定し、保存する値がURL形式になるように処理しています。

render_blockフックを使用して、公開ページにアイキャッチ画像ブロックを出力する際に処理を追加しています。個別記事ページを対象とし、URLが設定されている場合に、アイキャッチ画像をリンクで囲む仕組みです。URLが未設定の場合や、画像がない場合などは通常の表示を維持します。