2026年6月26日
2026年6月26日
WordPressの添付ファイルエラーを解決する方法
はじめに
WordPressのメディアライブラリで画像をクリックすると「添付ファイルが見つかりません」と表示される・get_attached_file()が空を返してサムネイルが表示されない・投稿削除後もwp-content/uploads/に画像ファイルが残り続けてディスクを圧迫する・プログラムから添付ファイルを作成したのにメタデータが正しく生成されないといった問題は、WordPressの添付ファイル管理システムを理解することで解決できます。
症状・原因
- 添付ファイルのメタデータ(
_wp_attachment_metadata)が壊れているか存在しないため、画像情報を取得できない - ファイルを直接
uploads/にコピーしたためWordPressのメディアライブラリに登録されていない - 投稿削除時に
delete_post()ではなくwp_delete_post()を使っていないため添付ファイルが残存する _wp_attached_fileメタキーのパスが環境移行後に古い絶対パスのまま更新されていない
解決手順
ステップ1:添付ファイルの状態を診断する
# 添付ファイルのメタデータを確認
wp eval "
\$meta = wp_get_attachment_metadata(123);
print_r(\$meta);
"
# _wp_attached_file の値を確認(相対パス)
wp post meta get 123 _wp_attached_file
# 実際のファイルが存在するか確認
wp eval "
\$file = get_attached_file(123);
echo 'Path: ' . \$file . PHP_EOL;
echo 'Exists: ' . (file_exists(\$file) ? 'yes' : 'no') . PHP_EOL;
"
# 孤立した添付ファイルを特定(投稿が存在しない添付)
wp eval "
\$orphans = get_posts([
'post_type' => 'attachment',
'post_parent' => 0,
'post_status' => 'inherit',
'posts_per_page' => 20,
'fields' => 'ids',
]);
echo 'Orphaned attachments: ' . implode(', ', \$orphans);
"
# メタデータがない添付ファイルを特定
wp post list --post_type=attachment --posts_per_page=50 --fields=ID,post_title
ステップ2:添付ファイルのメタデータを修復する
// ✅ 壊れたメタデータを再生成する
function my_repair_attachment_metadata(int $attachment_id): bool {
require_once ABSPATH . 'wp-admin/includes/image.php';
$file = get_attached_file($attachment_id);
if (!$file || !file_exists($file)) {
// _wp_attached_file が古いパスの場合は修正
$uploads = wp_upload_dir();
$old_meta = get_post_meta($attachment_id, '_wp_attached_file', true);
$new_path = $uploads['basedir'] . '/' . $old_meta;
if (file_exists($new_path)) {
update_post_meta($attachment_id, '_wp_attached_file', $old_meta);
$file = $new_path;
} else {
return false;
}
}
$metadata = wp_generate_attachment_metadata($attachment_id, $file);
if (empty($metadata)) {
return false;
}
return (bool) wp_update_attachment_metadata($attachment_id, $metadata);
}
// ✅ WP-CLI で全添付ファイルのメタデータを再生成
// wp media regenerate --yes
# メタデータを一括修復
wp eval "
\$ids = get_posts([
'post_type' => 'attachment',
'post_mime_type' => 'image',
'posts_per_page' => -1,
'fields' => 'ids',
]);
foreach (\$ids as \$id) {
require_once ABSPATH . 'wp-admin/includes/image.php';
\$file = get_attached_file(\$id);
if (\$file && file_exists(\$file)) {
\$meta = wp_generate_attachment_metadata(\$id, \$file);
wp_update_attachment_metadata(\$id, \$meta);
echo 'Fixed: ' . \$id . PHP_EOL;
}
}
"
ステップ3:ファイルをメディアライブラリに正しく登録する
// ✅ 既存ファイルをメディアライブラリに登録する
function my_register_existing_file(string $file_path, int $parent_post_id = 0): int|WP_Error {
require_once ABSPATH . 'wp-admin/includes/image.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
if (!file_exists($file_path)) {
return new WP_Error('file_not_found', 'ファイルが見つかりません: ' . $file_path);
}
$uploads = wp_upload_dir();
$filename = basename($file_path);
$mime = wp_check_filetype($filename)['type'] ?: 'application/octet-stream';
// アップロードディレクトリ相対パスを計算
$relative = str_replace($uploads['basedir'] . '/', '', $file_path);
$attachment = [
'post_mime_type' => $mime,
'post_title' => sanitize_file_name(pathinfo($filename, PATHINFO_FILENAME)),
'post_content' => '',
'post_status' => 'inherit',
'post_parent' => $parent_post_id,
];
$attachment_id = wp_insert_attachment($attachment, $file_path, $parent_post_id);
if (is_wp_error($attachment_id)) {
return $attachment_id;
}
// _wp_attached_file を相対パスで登録
update_post_meta($attachment_id, '_wp_attached_file', $relative);
// メタデータを生成
$metadata = wp_generate_attachment_metadata($attachment_id, $file_path);
wp_update_attachment_metadata($attachment_id, $metadata);
return $attachment_id;
}
ステップ4:孤立した添付ファイルを整理する
// ✅ 投稿が削除された添付ファイルを検出・削除
function my_cleanup_orphaned_attachments(bool $dry_run = true): array {
$deleted = [];
$attachments = get_posts([
'post_type' => 'attachment',
'post_status' => 'inherit',
'post_parent' => 0,
'posts_per_page' => 100,
'fields' => 'ids',
]);
foreach ($attachments as $id) {
// この添付ファイルを参照している投稿があるか確認
$used_in = get_post_meta($id, '_thumbnail_id', false);
// メタデータ内で参照されているか確認(post_content内の画像など)
global $wpdb;
$referenced = $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->posts}
WHERE post_content LIKE %s AND post_status = 'publish'",
'%' . $wpdb->esc_like(wp_get_attachment_url($id)) . '%'
));
if (empty($used_in) && !$referenced) {
$deleted[] = $id;
if (!$dry_run) {
wp_delete_attachment($id, true); // true = ファイルも削除
}
}
}
return $deleted;
}
// ✅ 添付ファイルを投稿ごと削除(ファイルも削除)
function my_delete_attachment_with_file(int $attachment_id): bool {
return (bool) wp_delete_attachment($attachment_id, true);
}
ステップ5:添付ファイルのURLとパスを正しく取得する
// ✅ 添付ファイルのURL・パスを取得する正しい方法
$attachment_id = 123;
// ファイルのURLを取得
$url = wp_get_attachment_url($attachment_id);
// 特定サイズのURLを取得
$thumb_url = wp_get_attachment_image_url($attachment_id, 'thumbnail');
$medium_url = wp_get_attachment_image_url($attachment_id, 'medium');
// img タグ全体を出力(srcset含む)
echo wp_get_attachment_image($attachment_id, 'large', false, [
'class' => 'my-image',
'alt' => esc_attr(get_post_meta($attachment_id, '_wp_attachment_image_alt', true)),
]);
// ファイルの絶対パスを取得
$file_path = get_attached_file($attachment_id);
// MIME タイプを取得
$mime = get_post_mime_type($attachment_id);
// メタデータを取得(幅・高さ・サイズ一覧)
$meta = wp_get_attachment_metadata($attachment_id);
$width = $meta['width'] ?? 0;
$height = $meta['height'] ?? 0;
// ✅ アイキャッチ画像として設定
set_post_thumbnail($post_id, $attachment_id);
// ✅ 特定投稿に紐付けた添付ファイル一覧を取得
$attached = get_posts([
'post_type' => 'attachment',
'post_parent' => $post_id,
'numberposts' => -1,
]);
注意事項
wp_delete_post()とwp_delete_attachment()は異なります。添付ファイルを削除する場合は必ずwp_delete_attachment($id, true)を使用してください。第2引数trueを指定しないと投稿レコードは削除されますが実際のファイルはuploads/に残ります- 孤立した添付ファイルを大量に削除する場合は、必ずバックアップを取ってから
$dry_run = falseに変更してください。wp_get_attachment_image_src()でショートコードやページビルダーから参照されているファイルは削除対象外にすること
まとめ
WordPressの添付ファイルエラーの解決は①wp_get_attachment_metadata()でメタ確認・get_attached_file()でパス存在確認・孤立添付をpost_parent:0で特定、②wp_generate_attachment_metadata()+wp_update_attachment_metadata()でメタ再生成・_wp_attached_fileの相対パスを修正、③wp_insert_attachment()+_wp_attached_file更新+wp_generate_attachment_metadata()で既存ファイルをライブラリ登録、④wp_delete_attachment($id, true)で添付ファイルとファイルを同時削除・post_content内での参照チェック後に孤立ファイルを整理、⑤wp_get_attachment_url()/wp_get_attachment_image_url()/get_attached_file()で正しくURL・パスを取得の手順で解決します。