0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel / Storageで「環境ごとにFILESYSTEM_DISKが違う」時の事故を防ぐ

Last updated at Posted at 2025-09-07

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
localstorage/app を指すので、storage/app/public/collection_images/... を狙ってたまたま動くことがある。

▪️ 本番(FILESYSTEM_DISK=public
publicstorage/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);

.envconfig の確認ポイント

▪️ .env(例):

// ①
Storage::delete('collection_images/foo.jpg')
// ②
Storage::disk('public')->delete('collection_images/foo.jpg')

上記の①ようにdisk('public')disk('local')を書かないでしようすると
以下のFILESYSTEM_DISKに設定されているものが適用される。

.env
# 開発
FILESYSTEM_DISK=local

# 本番
FILESYSTEM_DISK=public

基本はFILESYSTEM_DISK=localにしておいて、以下のように使うのが吉

Storage::disk('public')->delete('collection_images/foo.jpg')

▪️ config/filesystems.php(抜粋):

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 に追加:

config/app.php
'media_disk' => env('MEDIA_DISK', 'public'),

.env:

.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') を明示し、パスはディスクのルート相対で記述するのがベストプラクティス。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?