2026年5月31日

2026年5月31日

WordPressのメディアライブラリを整理・管理する方法

はじめに

「メディアライブラリに数千枚の画像が無秩序に溜まっている」「使っていない画像を削除してサーバー容量を節約したい」「年月ごとのフォルダ整理をもっとうまくやりたい」——メディアライブラリの整理はWordPressサイトの長期運用で重要な作業です。

症状・原因

WordPressはデフォルトでアップロードをwp-content/uploads/YYYY/MM/に年月別で保存します。フォルダ階層なしで管理するとファイル数が増えるにつれ管理が困難になり、未使用メディアがサーバー容量を圧迫します。

解決手順

ステップ1:メディアライブラリの現状を把握する

// functions.php: メディアの統計情報を取得
function get_media_stats() {
    $attachments = wp_count_attachments();
    $total = 0;

    foreach ( $attachments as $type => $count ) {
        $total += $count;
    }

    // アップロードディレクトリのサイズを計算
    $upload_dir = wp_upload_dir();
    $base_dir   = $upload_dir['basedir'];

    $size = 0;
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator( $base_dir )
    );
    foreach ( $iterator as $file ) {
        if ( $file->isFile() ) {
            $size += $file->getSize();
        }
    }

    return [
        'total_files'   => $total,
        'total_size_mb' => round( $size / 1024 / 1024, 1 ),
        'upload_path'   => $base_dir,
    ];
}
# WP-CLIでメディア情報を確認
wp media list --fields=ID,post_title,post_mime_type,guid

# MIMEタイプ別にカウント
wp media list --format=json | python3 -c "
import json,sys
data = json.load(sys.stdin)
types = {}
for item in data:
    t = item.get('post_mime_type','')
    types[t] = types.get(t, 0) + 1
for t,c in sorted(types.items(), key=lambda x: -x[1]):
    print(f'{c:5d}  {t}')
"

ステップ2:未使用メディアを検出・削除する

// functions.php: 未使用の添付ファイルを検出
function get_unused_attachments( $limit = 100 ) {
    global $wpdb;

    // どの投稿にも添付されておらず、
    // post_contentやpost_metaでも参照されていないファイルを検出
    $attachments = $wpdb->get_results(
        "SELECT ID, post_title, guid
         FROM {$wpdb->posts}
         WHERE post_type = 'attachment'
         AND post_parent = 0
         LIMIT {$limit}",
        ARRAY_A
    );

    $unused = [];
    foreach ( $attachments as $attachment ) {
        $id  = $attachment['ID'];
        $url = $attachment['guid'];

        // post_contentで参照されているか確認
        $found = $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->posts}
             WHERE post_content LIKE %s
             AND post_type != 'attachment'",
            '%' . $wpdb->esc_like( basename( $url ) ) . '%'
        ) );

        if ( ! $found ) {
            $unused[] = $attachment;
        }
    }

    return $unused;
}
# WP-CLIで未使用メディアを削除するスクリプト
# ※ 実行前に必ずバックアップを取得すること

# 孤立した添付ファイル(親投稿なし)を一覧表示
wp post list --post_type=attachment --post_parent=0 --format=ids

# 特定の期間より古い未使用添付ファイルを削除(慎重に実行)
wp post list \
  --post_type=attachment \
  --post_parent=0 \
  --date_query_before="2022-01-01" \
  --format=ids | xargs -I {} wp post delete {} --force

ステップ3:メディアライブラリをフォルダで整理する

【フォルダ管理プラグインの選択肢】

1. Filester - File Manager Pro(有料・高機能)
   - フォルダ作成・ドラッグ&ドロップ移動
   - メディアライブラリとファイルマネージャを統合

2. Real Media Library(有料)
   - WordPress管理画面にフォルダツリーを追加
   - REST API対応

3. Media Library Folders(無料/有料)
   - 無料版でもフォルダ作成・整理が可能
   - 物理的なフォルダ構成を反映

【フォルダ管理を使わない場合の整理方針】
- 年月別(デフォルト): wp-content/uploads/2024/01/
- テーマ別: wp-content/uploads/category-name/ ← 手動管理が必要
- 設定 → メディア → 「年月ベースのフォルダ」のチェックを外すと
  wp-content/uploads/ にフラットに保存される(逆に管理しにくくなる場合も)
// functions.php: アップロードディレクトリを投稿タイプ別に変更
add_filter( 'upload_dir', function( $dirs ) {
    // 現在編集中の投稿タイプを取得
    $post_id   = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
    $post_type = $post_id ? get_post_type( $post_id ) : '';

    if ( $post_type === 'portfolio' ) {
        $dirs['subdir'] = '/portfolio' . $dirs['subdir'];
        $dirs['path']   = $dirs['basedir'] . $dirs['subdir'];
        $dirs['url']    = $dirs['baseurl'] . $dirs['subdir'];
    }

    return $dirs;
} );

ステップ4:登録済み画像サイズを整理する

// functions.php: 不要な画像サイズを削除して容量を節約

// WordPressデフォルトの画像サイズを無効化
add_filter( 'intermediate_image_sizes_advanced', function( $sizes ) {
    // 不要なサイズを削除
    unset( $sizes['medium_large'] ); // 768px幅(使わない場合)

    return $sizes;
} );

// テーマで独自に登録した画像サイズを追加
add_action( 'after_setup_theme', function() {
    // 古いサイズを削除
    remove_image_size( 'old-size-name' );

    // 新しいサイズを追加
    add_image_size( 'card-thumbnail', 400, 300, true );  // クロップあり
    add_image_size( 'hero-image',     1200, 630, true ); // OGP用
} );
# 既存の画像を新しいサイズで再生成
wp media regenerate --yes

# 特定の画像のみ再生成
wp media regenerate 123 456 789

# 不要なサイズのファイルをWP-CLIで削除
# ※ WP CLIのmedia clean-sizesコマンドはサードパーティ
wp eval '
$upload_dir = wp_upload_dir();
$base = $upload_dir["basedir"];
// 古いサイズのファイルを削除(パターンマッチ)
$files = glob($base . "/**/*-768x*");
foreach ($files as $file) {
    unlink($file);
    echo "Deleted: " . basename($file) . "\n";
}
'

ステップ5:テンプレートでメディアを適切に出力する

// テンプレートでの画像出力ベストプラクティス

// wp_get_attachment_image() を使う(推奨)
$image_id = get_post_thumbnail_id();
echo wp_get_attachment_image( $image_id, 'card-thumbnail', false, [
    'class'   => 'card-image',
    'loading' => 'lazy',
    'alt'     => get_the_title(),
] );

// レスポンシブ画像をsrcsetで出力
echo wp_get_attachment_image( $image_id, 'large', false, [
    'sizes' => '(max-width: 768px) 100vw, 50vw',
] );

// 画像URLのみ取得
$url = wp_get_attachment_image_url( $image_id, 'medium' );

// 画像の全メタ情報を取得
$meta = wp_get_attachment_metadata( $image_id );
// $meta['width'], $meta['height'], $meta['sizes'] で各サイズ情報にアクセス

// WebP変換後のURLを取得(WordPress 5.8+)
$srcset = wp_get_attachment_image_srcset( $image_id, 'large' );

注意事項

  • 未使用メディアの削除は元に戻せません。削除前に必ずバックアップを取得し、本当に使われていないか確認してから実行してください。外部からのリンクや古いキャッシュが残っている場合があります。
  • 画像サイズを変更した場合、既存の画像は自動的に再生成されません。wp media regenerateコマンドで既存画像を再生成してください。大量の画像がある場合は時間がかかります。
  • アップロードディレクトリをカスタマイズする場合、マルチサイト環境では別途考慮が必要です。

まとめ

メディアライブラリの整理は「WP-CLIで現状把握→未使用添付ファイルを安全に削除→フォルダ管理プラグインで整理→不要な画像サイズを削除してwp media regenerateで再生成→wp_get_attachment_image()でsrcset対応の最適な出力」の流れで整備します。関連記事:WordPress画像をWebPに変換して最適化する方法WordPressで画像の遅延読み込みを設定する方法

お気軽にご相談ください

お見積りへ お問い合わせへ