Laravel で用途別に Storage ディスクを作成してみる
前書き
先日、Laracon 2024 の後に local
ディスクの root
のパスが、サクッと storage_path('app')
から storage_path('app/private')
に変更になったのは記憶に新しい所ですね。(これは、Laracon 2024 で発表した新機能に伴う変更だったとは言え、ちょっとビックリでしたね)
それはさておき、今回のブログでは、ファイルアップロード時などに使う Storage 機能を local
, public
, s3
などを本体コード中からは直接呼び出さず、適宜用途別のディスクを作成して、それ経由で呼び出してみようという内容です。
本題
今回は、以下の2つの用途のディスクを作成します。
- 「プロフィール画像」は、一般に公開する画像で、本番では
s3
で保存するが、開発環境ではpublic
で保存する。 - 「レポートPDF」は秘密の PDF で、本番では
ftp
で FTP サーバに転送するが、開発環境では、local
で保存する。
という事で、config/filesystems.php
は以下のようになりました。(もう結論かよ…😖)
<?php
$production = env('APP_ENV') === 'production';
$local = [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true,
'throw' => false,
];
$public = [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
];
$s3 = [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
// 多いので以下略、通常通り記載する
];
// 追加
$ftp = [
'driver' => 'ftp',
'host' => env('FTP_HOST'),
'username' => env('FTP_USERNAME'),
'password' => env('FTP_PASSWORD'),
];
return [
'default' => env('FILESYSTEM_DISK', 'local'),
'disks' => [
'local' => $local,
'public' => $public,
's3' => $s3,
// プロフィール画像用
'PROFILE_DISK' => $production ?
[...$s3, 'root' => 'profile'] :
[...$public, 'root' => storage_path('app/public/profile'), 'url' => '/storage/profile'],
// レポート用(秘密のファイル)
'REPORT_DISK' => $production ?
[...$ftp, 'root' => 'report'] :
[...$local, 'root' => storage_path('app/private/report')],
],
// 以下略
];
一番最初で本番環境か否かを $production
に格納しています。続けて $local
, $public
, $s3
にそれぞれいつものデフォルトの設定を格納しています。(FTP も追加しています)
そして、return
の中で、'PROFILE_DISK'
と 'REPORT_DISK'
にそれぞれの用途に応じた設定を格納しています。
'PROFILE_DISK'
は、本番環境では s3
で profile
ディレクトリに保存し、開発環境では public
で profile
ディレクトリに保存するように設定しています。
'REPORT_DISK'
は、本番環境では ftp
で report
ディレクトリに保存し、開発環境では local
で report
ディレクトリに保存するように設定しています。
以上の設定で、環境に応じて適当に切り替わってくれます。(設定内容が多くなる場合は、適宜クラスファイルを利用するのもありかと思います)
上記を使う
本番でも開発でも使い方は同じです。
例えば、プロフィール画像を保存する時は、以下の感じになります。
$path = Storage::disk('PROFILE_DISK')->putFile('', $request->file('myfile'));
putFile()
は、第一引数に保存先のパスを指定できますが、ここでは空で指定しています。もし 2024
とかを指定すれば、profile/2024
ディレクトリに保存されます。
今回はパスを指定していないので、$path
には、ファイル名のみが格納されます。(例:g7g4cmtbmsbG.jpg ← 実際はもっと長い)
ですので、そのファイル名のみを DB に格納します。(もし profile
のパスも含めて保存したい場合は、設定ファイルで直してやります)
テンプレートで URL を表示する際は、以下の感じになります。
<img src="{{ Storage::disk('PROFILE_DISK')->url('g7g4cmtbmsbG.jpg') }}" alt="">
ファイル名は直書きしましたが、実際は DB から取得して値を埋め込んでやります。
疲れてきたので FTP の場合は省略しますが、保存方法は同じです。(但し FTP の場合は、予め転送先にディレクトリ(フォルダ)を作成する必要があります)
雑感
ちなみに私は、VSCode を使ってこのブログ記事を書いていますが、VSCode のデフォルトだと、マークダウンファイルに対して、Copilot が効かないですね🥲
ですが、以下の設定を設定ファイルに追記すれば、マークダウンファイルでも Copilot が効くようになります 👍
"github.copilot.enable":{
"*": true,
"plaintext": false,
"markdown": true, // ← ここ
"scminput": false
},
これで Copilot が先読みして色々サジェストしてくれるので、ブログ編集作業も捗ります。
「vscode の中級者向け講座」がこんな所に。
【2024年】(中級)vscode をもっと使いこなし、コーディングを高速化しよう!
キャンペーンコードは、その年月の YYYY_MM 形式(例:2024_09)
Discussion