Storage::delete()
ではなく Storage::disk('public')
を明示する理由
TL;DR
▪️ 開発では FILESYSTEM_DISK=local
、本番では FILESYSTEM_DISK=public
のようにデフォルトディスクが異なる構成だと、
Storage::delete('public/collection_images/foo.jpg')
のような書き方は環境によって消す場所がズレる。
▪️ 常に使いたいディスクを明示して、パスはそのディスクのルート相対で書くのが安全。
→ Storage::disk('public')->delete('collection_images/foo.jpg')
よくある症状
// NG例:環境によって動いたり動かなかったり…
Storage::delete('public/collection_images/'.$image->image_path);
▪️ 開発(FILESYSTEM_DISK=local
)
→ local
は storage/app
を指すので、storage/app/public/collection_images/...
を狙ってたまたま動くことがある。
▪️ 本番(FILESYSTEM_DISK=public
)
→ public
は storage/app/public
。ここでさらに 'public/...'
を付けると
storage/app/public/public/collection_images/...
のように二重で public
を踏んで失敗(または別場所を触る)。
↓
つまり、**「デフォルトのディスクが違う環境」+「パスに public
を含めている」**の組合せが破綻ポイントです。
正しい書き方(安全策)
1) ディスクを明示する
// ✅ 常に "public" ディスクを使う(保存/削除/存在確認 等)
Storage::disk('public')->delete('collection_images/'.$image->image_path);
Storage::disk('public')->exists('collection_images/'.$image->image_path);
Storage::disk('public')->putFile('collection_images', $uploadedFile);
▪️ パスはそのディスクのルート相対で。public/
をパスに二度書かない。
▪️ 本番/開発で FILESYSTEM_DISK
が違っても、常に同じ場所を扱える。
2) store()/storeAs()
を使う場合
// 保存(第二引数に 'public' を渡す/明示する)
$path = $request->file('image')->store('collection_images', 'public'); // ex: collection_images/xxx.jpg
// 削除(保存時と同じディスクに合わせる)
Storage::disk('public')->delete($path);
.env
と config
の確認ポイント
▪️ .env
(例):
// ①
Storage::delete('collection_images/foo.jpg')
// ②
Storage::disk('public')->delete('collection_images/foo.jpg')
上記の①ようにdisk('public')
やdisk('local')
を書かないでしようすると
以下のFILESYSTEM_DISK
に設定されているものが適用される。
# 開発
FILESYSTEM_DISK=local
# 本番
FILESYSTEM_DISK=public
基本はFILESYSTEM_DISK=local
にしておいて、以下のように使うのが吉
Storage::disk('public')->delete('collection_images/foo.jpg')
▪️ config/filesystems.php
(抜粋):
'default' => env('FILESYSTEM_DISK', 'local'),
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
]
▪️ 公開配信するならリンク作成も必須:
php artisan storage:link # public/storage → storage/app/public へのシンボリックリンク
具体的な修正例
修正前(不安定)
// × デフォルトディスク依存 + パスに public が含まれてしまっている
Storage::delete('public/collection_images/'.$image->image_path);
修正後(安定)
// ○ ディスクを明示 + ディスクのルート相対パスで記述
Storage::disk('public')->delete('collection_images/'.$image->image_path);
補足:
同じ理由で exists, put, copy, move, url なども disk を明示した方が安全です。
さらに堅牢にする(拡張案)
1) 「使うディスク名」を設定化して共通利用
config/app.php
に追加:
'media_disk' => env('MEDIA_DISK', 'public'),
.env
:
MEDIA_DISK=public
利用側:
$disk = Storage::disk(config('app.media_disk', 'public'));
$disk->delete('collection_images/'.$image->image_path);
2) アップロード〜削除を「同一ディスクで」一貫
$disk = Storage::disk('public');
$path = $request->file('image')->store('collection_images', $disk->getDriver()->getAdapter()->getPathPrefix() ? 'public' : 'public');
// ↑ store() は第二引数に 'public'(ディスク名)を渡すのがシンプル
$disk->delete($path);
まとめ
▪️ 環境ごとに FILESYSTEM_DISK
が違うなら、Storage::delete()
のようにデフォルトに乗る書き方は危険。
▪️ Storage::disk('public')
を明示し、パスはディスクのルート相対で記述するのがベストプラクティス。