関連記事ブロックのリンク切れ(投稿が見つかりません)を一覧表示する方法

実際に使用した商品をレビューしています。アフィリエイト広告リンクを含みます。
関連記事ブロックのリンク切れ(投稿が見つかりません)を一覧表示する方法
初心者

関連記事でリンク切れがある。
記事が多くて、どこにあるか把握できない。
一括で確認する方法ってないの?

そんな疑問に答えます。

SWELLの標準機能だけでは実現できませんが、カスタマイズコードを追加することで、リンク切れの一覧を表示できるようになります。

以下の画像は、本記事で紹介するカスタマイズを実装した画面です。関連記事ブロックのリンク切れを一覧表示しています。

リンク切れの関連記事ブロック一覧を表示させたサンプル
この記事を書いた人
  • IT業界24年のベテラン エンジニア
  • WordPressで企業サイトの構築しています
  • 取り扱いWordPressテーマは300個オーバー
SWELLマニアの かんた です

目次

【基本知識】関連記事ブロックとは?

【基本知識】関連記事ブロックとは?
【基本知識】関連記事ブロックとは?

まずは関連記事ブロックの基本について解説します。

関連記事ブロックはSWELL固有のカスタムブロック

関連記事ブロックはWordPressテーマSWELLに内包されているカスタムブロックです。

【SWELL】関連記事ブロック
【SWELL】関連記事ブロック

投稿記事の下に自動的に表示される関連記事のことではありません。

サイト内の記事、外部サイトの記事を指定することでオシャレなブログカードでリンクを表示させるブロックです。

サポートしている記事

  1. サイト内の記事
  2. 外部サイトの記事

リンクが切れた場合どうなる?

関連記事ブロックで指定したリンク先の記事を削除すると、「投稿が見つかりません」と表示されます。
ブロック自体は自動で削除されず、そのまま残ります。

初心者

そのまま残すのは…

リンク切れの関連記事ブロックを把握したい

リンク切れの関連記事ブロックを把握したい

リンク切れの記事を把握するカスタマイズについてです。

カスタマイズ方法

以下のコードを追加します。追加場所は子テーマを有効化している場合は、子テーマのfunctions.php。そうでない場合はCode Snippetsプラグインなどのコード管理ツールを利用してください。

コード

/**
 * SWELL関連記事リンク切れスキャン(投稿一覧ページ限定表示版)
 * (修正あり)
 */
function find_broken_swell_post_links() {
    // 1. 管理者権限チェック
    if (!current_user_can('manage_options')) return;

    // 2. 投稿一覧ページ(edit.php)以外では実行・表示しない
    $screen = get_current_screen();
    if ( !isset($screen->id) || $screen->id !== 'edit-post' ) {
        return;
    }

    global $wpdb;

    // 公開済みの投稿をDBから直接取得
    $results = $wpdb->get_results(
        "SELECT ID, post_title, post_content
         FROM $wpdb->posts
         WHERE post_status = 'publish'
         AND post_type = 'post'"
    );

    $broken_list = [];
    $debug_info  = [];

    if ($results) {
        foreach ($results as $post) {

            // Gutenbergブロックを構造的に解析
            $blocks = parse_blocks($post->post_content);

            foreach ($blocks as $block) {

                // SWELL関連記事ブロック(loos/post-link)のみを対象とする
                if ($block['blockName'] !== 'loos/post-link') continue;

                $attrs = isset($block['attrs']) ? $block['attrs'] : [];

                // リンク先の投稿IDを取得
                $post_id = 0;
                if (!empty($attrs['linkData']['id'])) {
                    $post_id = (int)$attrs['linkData']['id'];
                } elseif (!empty($attrs['postID'])) {
                    $post_id = (int)$attrs['postID'];
                }

                if ($post_id <= 0) continue;

                // リンク先記事のステータスを確認
                $target_status = get_post_status($post_id);
                $target_title  = isset($attrs['linkData']['title']) ? $attrs['linkData']['title'] : '不明なタイトル';
                $status_label  = $target_status ? $target_status : '完全削除済み';

                // 全検出データの記録(デバッグ用)
                $debug_info[] = [
                    'parent_title' => $post->post_title,
                    'target_id'    => $post_id,
                    'target_name'  => $target_title,
                    'status'       => $status_label
                ];

                // リンク切れ判定:ステータスが取得できない、またはゴミ箱(trash)の場合
                if (!$target_status || $target_status === 'trash') {
                    $broken_list[] = [
                        'title'       => $post->post_title,
                        'url'         => get_edit_post_link($post->ID),
                        'target_id'   => $post_id,
                        'target_name' => $target_title
                    ];
                }
            }
        }
    }

    // ===== 管理画面への表示出力 =====
    echo '<div style="background:#fff; padding:20px; border:4px solid #ff4d4d; margin:20px 0; border-radius:8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">';
    echo '<h2 style="color:#d63638; margin-top:0;">🔍 SWELL関連記事 リンク切れスキャン</h2>';

    if (!empty($broken_list)) {
        echo '<p style="font-weight:bold; color:#d63638;">⚠️ 以下の投稿内でリンク切れが検出されました:</p>';
        echo '<ul style="background:#fff5f5; padding:15px; border:1px solid #ffcaca; list-style-type: none;">';

        foreach ($broken_list as $item) {
            echo '<li style="margin-bottom:12px; border-left: 4px solid #d63638; padding-left: 15px;">';
            echo '<a href="' . esc_url($item['url']) . '" target="_blank" style="color:#2271b1; font-weight:bold; font-size:1.1em; text-decoration:none;">';
            echo esc_html($item['title']) . ' ↗</a><br>';
            echo '<span style="color:#666; font-size:0.9em;">└ 切れている記事: <b>' . esc_html($item['target_name']) . '</b> (ID:' . esc_html($item['target_id']) . ')</span>';
            echo '</li>';
        }

        echo '</ul>';
    } else {
        echo '<p style="background:#f0fff0; padding:12px; font-weight:bold; color:#00a32a; border:1px solid #c6e1c6;">✅ 現在、リンク切れの関連記事ブロックは見つかりませんでした。</p>';
    }

    // 詳細内訳(折りたたみ表示)
    if (!empty($debug_info)) {
        echo '<details style="margin-top:20px; color:#666;"><summary style="cursor:pointer;">全関連記事ブロックの検出内訳を表示</summary>';
        echo '<table style="width:100%; border-collapse:collapse; margin-top:10px; font-size:13px;">';
        echo '<tr style="background:#eee; text-align:left;">
                <th style="padding:8px;">掲載記事(親)</th>
                <th style="padding:8px;">リンク先</th>
                <th style="padding:8px; text-align:center;">ID</th>
                <th style="padding:8px; text-align:center;">状態</th>
              </tr>';

        foreach ($debug_info as $info) {
            $is_broken = ($info['status'] === 'trash' || $info['status'] === '完全削除済み');
            $color = $is_broken ? '#d63638' : '#00a32a';

            echo '<tr style="border-bottom:1px solid #eee;">';
            echo '<td style="padding:8px;">' . esc_html($info['parent_title']) . '</td>';
            echo '<td style="padding:8px;">' . esc_html($info['target_name']) . '</td>';
            echo '<td style="padding:8px; text-align:center;">' . esc_html($info['target_id']) . '</td>';
            echo '<td style="padding:8px; text-align:center; color:' . $color . '; font-weight:bold;">' . esc_html($info['status']) . '</td>';
            echo '</tr>';
        }

        echo '</table></details>';
    } else {
        echo '<p style="color:#999; font-size:0.9em;">※サイト内に関連記事ブロックが1つも存在しません。</p>';
    }

    echo '</div>';
}

add_action('admin_notices', 'find_broken_swell_post_links');

コードを追加すると、ダッシュボード内投稿一覧上部にリンク切れが一覧で表示されます。

記事のタイトルはクリック可能です↓

クリックすると、該当ページのエディターが開きます↓

リンク先が切れている関連記事ブロックは「投稿が見つかりません。」と表示されるため、該当箇所を修正してください。

FAQ

FAQ

リンク先を削除したのにブログカードが表示される

キャッシュが原因の可能性があります。ブラウザキャッシュ、ダッシュボード内「SWELL設定」→「リセット」からキャッシュをクリアしてください。

コードは作業後も残しておいてよい?

リンク切れの確認が終わったら削除してください。
データベースへの問い合わせが発生するため、負荷の原因になります。

チェック対象はサイト内記事のみ?

はい、サイト内の記事のみが対象です。

まとめ

SWELLの関連記事ブロックでリンク切れを一覧表示する方法を紹介しました。

記事数が多いサイトで関連記事ブロックを利用している場合は、ぜひ活用してみてください。

よかったらシェアしてね!
  • URLをコピーしました!
目次