Laravel で用途別に Storage ディスクを作成してみる

2024/10/01に公開

前書き

先日、Laracon 2024 の後に local ディスクの root のパスが、サクッと storage_path('app') から storage_path('app/private')変更になったのは記憶に新しい所ですね。(これは、Laracon 2024 で発表した新機能に伴う変更だったとは言え、ちょっとビックリでしたね)

それはさておき、今回のブログでは、ファイルアップロード時などに使う Storage 機能を local, public, s3 などを本体コード中からは直接呼び出さず、適宜用途別のディスクを作成して、それ経由で呼び出してみようという内容です。

本題

今回は、以下の2つの用途のディスクを作成します。

  1. 「プロフィール画像」は、一般に公開する画像で、本番では s3 で保存するが、開発環境では public で保存する。
  2. 「レポート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' は、本番環境では s3profile ディレクトリに保存し、開発環境では publicprofile ディレクトリに保存するように設定しています。

'REPORT_DISK' は、本番環境では ftpreport ディレクトリに保存し、開発環境では localreport ディレクトリに保存するように設定しています。

以上の設定で、環境に応じて適当に切り替わってくれます。(設定内容が多くなる場合は、適宜クラスファイルを利用するのもありかと思います)

上記を使う

本番でも開発でも使い方は同じです。
例えば、プロフィール画像を保存する時は、以下の感じになります。

$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