本文へ移動
Laravel Tips

ファイルの保存(ストレージ)

ファイルを保存・取り出し・削除する Storage の使い方を説明します。ディスクの設定、アップロード、URL、公開と非公開、テストの書き方も扱います。

アプリでは、ユーザーがアップロードした写真や、書き出したデータなど、ファイルをしまう場面がよくあります。Laravel は、ファイルの置き場所がどこでも、同じ書き方で扱えるようにしてくれます。置き場所は、サーバーの中のフォルダでも、Amazon S3(インターネット上のファイル置き場)でもかまいません。これは、Flysystem という PHP のパッケージのおかげです。手元の開発のときは自分のパソコンのフォルダに、本番ではクラウドに、というように、置き場所を切りかえても、書き方は変わりません。

設定#

ファイルの設定は config/filesystems.php にあります。ここで、「ディスク」(ファイルの置き場所の設定1つぶん)をいくつでも決められます。ディスクは、置き場所の種類(ドライバー)と、置く場所の組です。設定ファイルには、ドライバーごとの見本が入っています。好みや認証の情報(つなぐための ID や鍵)に合わせて直せます。

  • local ドライバーは、Laravel が動いているサーバーの中のファイルを扱います
  • sftp ドライバーは、SSH の鍵を使う FTP(ファイルを送る方法)です
  • s3 ドライバーは、Amazon の S3 というクラウドのファイル置き場に書きこみます

補足

ディスクはいくつでも作れます。同じドライバーを使うディスクが複数あってもかまいません。

local ドライバー#

local ドライバーでは、ファイルの場所を、filesystems 設定の root(根っことなるフォルダ)から見た場所で書きます。root は、ふつう storage/app/private フォルダです。そのため、次のコードは storage/app/private/example.txt に書きこみます。

php
use Illuminate\Support\Facades\Storage;

Storage::disk('local')->put('example.txt', 'Contents');

public ディスク#

アプリの filesystems 設定にある public ディスクは、だれでも見られる(公開する)ファイルのためのものです。ふつう、public ディスクは local ドライバーを使い、ファイルを storage/app/public に置きます。

public ディスクが local ドライバーのとき、そのファイルを Web から見られるようにするには、元のフォルダ storage/app/public から、先のフォルダ public/storage への、シンボリックリンク(別の場所を指すショートカットのようなもの)を作ります。

シンボリックリンクは、storage:link という Artisan コマンドで作れます。

bash
php artisan storage:link

ファイルを保存し、リンクも作ったら、asset ヘルパー関数で、そのファイルの URL を作れます。

php
echo asset('storage/file.txt');

filesystems 設定には、シンボリックリンクをさらに足せます。storage:link を動かすと、設定したリンクがすべて作られます。

php
'links' => [
    public_path('storage') => storage_path('app/public'),
    public_path('images') => storage_path('app/images'),
],

作ったリンクを消すには、storage:unlink を使います。

bash
php artisan storage:unlink

ドライバーごとの準備#

S3 ドライバーの設定#

S3 ドライバーを使う前に、Composer で Flysystem の S3 パッケージを入れます。

bash
composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies

config/filesystems.php には、S3 のディスクの設定が入っています。ふつうは、S3 の情報や認証の情報を、次の環境変数(.env に書く設定値)に書きます。設定ファイルが、この環境変数を読みます。

ini
AWS_ACCESS_KEY_ID=<your-key-id>
AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=<your-bucket-name>
AWS_USE_PATH_STYLE_ENDPOINT=false

これらの環境変数の名前は、AWS CLI(Amazon のコマンド)の名前と合わせてあります。

FTP ドライバーの設定#

FTP ドライバーを使う前に、Composer で Flysystem の FTP パッケージを入れます。

bash
composer require league/flysystem-ftp "^3.0"

Laravel は FTP にも対応していますが、標準の config/filesystems.php には見本が入っていません。FTP のディスクを作りたいときは、次の設定の例が使えます。

php
'ftp' => [
    'driver' => 'ftp',
    'host' => env('FTP_HOST'),
    'username' => env('FTP_USERNAME'),
    'password' => env('FTP_PASSWORD'),

    // 付けなくてもよい FTP の設定...
    // 'port' => env('FTP_PORT', 21),
    // 'root' => env('FTP_ROOT'),
    // 'passive' => true,
    // 'ssl' => true,
    // 'timeout' => 30,
],

SFTP ドライバーの設定#

SFTP ドライバーを使う前に、Composer で Flysystem の SFTP パッケージを入れます。

bash
composer require league/flysystem-sftp-v3 "^3.0"

SFTP も、標準の設定ファイルに見本が入っていません。SFTP のディスクを作りたいときは、次の設定の例が使えます。

php
'sftp' => [
    'driver' => 'sftp',
    'host' => env('SFTP_HOST'),

    // ふつうの認証(ユーザー名とパスワード)の設定...
    'username' => env('SFTP_USERNAME'),
    'password' => env('SFTP_PASSWORD'),

    // SSH の鍵で認証する設定(鍵に付けたパスワードも使う)...
    'privateKey' => env('SFTP_PRIVATE_KEY'),
    'passphrase' => env('SFTP_PASSPHRASE'),

    // ファイルとフォルダの権限の設定...
    'visibility' => 'private', // `private` = 0600, `public` = 0644
    'directory_visibility' => 'private', // `private` = 0700, `public` = 0755

    // 付けなくてもよい SFTP の設定...
    // 'hostFingerprint' => env('SFTP_HOST_FINGERPRINT'),
    // 'maxTries' => 4,
    // 'passphrase' => env('SFTP_PASSPHRASE'),
    // 'port' => env('SFTP_PORT', 22),
    // 'root' => env('SFTP_ROOT', ''),
    // 'timeout' => 30,
    // 'useAgent' => true,
],
ドライバー 説明
local サーバーの中のファイルを扱う
sftp SSH の鍵を使う FTP で扱う。Composer で SFTP パッケージが必要
ftp FTP で扱う。Composer で FTP パッケージが必要
s3 Amazon S3 などに書きこむ。Composer で S3 パッケージが必要
scoped 既存のディスクの、決まった場所の中だけを扱う
read-through 2つのディスクのあいだで、止めずにファイルを引っ越す

範囲を絞ったディスク・読み取り専用のディスク・読みながら移すディスク#

範囲を絞る(scoped)#

scoped ディスクは、すべての道すじの前に、決まった場所(プレフィックス)が自動で付くディスクです。作る前に、Composer で追加の Flysystem パッケージを入れます。

bash
composer require league/flysystem-path-prefixing "^3.0"

scoped ドライバーを使うと、すでにあるどのディスクからも、場所を絞ったディスクを作れます。たとえば、s3 ディスクのうち、決まった場所の中だけを扱うディスクにできます。そのディスクで扱うファイルは、すべて、決めた場所の中に限られます。

php
's3-videos' => [
    'driver' => 'scoped',
    'disk' => 's3',
    'prefix' => 'path/to/videos',
],

読み取り専用(read-only)#

「読み取り専用」のディスクは、書きこみができないディスクです。read-only の設定を使う前に、Composer で追加の Flysystem パッケージを入れます。

bash
composer require league/flysystem-read-only "^3.0"

そのうえで、ディスクの設定に read-only を足します。

php
's3-videos' => [
    'driver' => 's3',
    // ...
    'read-only' => true,
],

読みながら移す(read-through)#

read-through ディスクは、サービスを止めずに、ディスクのあいだでファイルを引っ越すためのものです。ファイルを読むとき、Laravel はまず主のディスクを調べます。ファイルが予備(フォールバック)のディスクにしか無いときは、予備のディスクから読み、次のアクセスのために、主のディスクにコピーします。

php
'assets' => [
    'driver' => 'read-through',
    'primary' => 's3',
    'fallback' => 'legacy-s3',
],

書きこみとフォルダの一覧には、主のディスクを使います。ファイルがあるかの確認と、ファイルの情報の取得には、どちらのディスクも使います。このときは、主のディスクへのコピーはしません。予備のファイルを主のディスクへコピーするのに失敗しても、ふつうは、読むこと自体は成功します。代わりに例外を出したいときは、throw_on_promotion_failure 設定を true にします。

Amazon S3 と互換のファイル置き場#

標準の filesystems 設定には、s3 ディスクの設定が入っています。このディスクは、Amazon S3 だけでなく、S3 と互換のファイル置き場のサービスでも使えます。たとえば、RustFS・DigitalOcean Spaces・Vultr Object Storage・Cloudflare R2・Hetzner Cloud Storage です。

ふつうは、ディスクの認証の情報を、使いたいサービスのものに変えたあと、endpoint 設定の値を変えるだけで済みます。この値は、ふつう AWS_ENDPOINT 環境変数で決めます。

php
'endpoint' => env('AWS_ENDPOINT', 'https://rustfs:9000'),

ディスクを選ぶ#

設定したどのディスクも、Storage ファサード(:: で呼べる窓口)で扱えます。たとえば、put で、標準のディスクにアバター(プロフィール画像)を保存できます。disk を先に呼ばずに Storage のメソッドを呼ぶと、標準のディスクが使われます。

php
use Illuminate\Support\Facades\Storage;

Storage::put('avatars/1', $content);

複数のディスクを使うアプリでは、disk で、決まったディスクのファイルを扱えます。

php
Storage::disk('s3')->put('avatars/1', $content);

その場でディスクを作る#

アプリの filesystems 設定に書いていない設定で、実行中にその場でディスクを作りたいことがあります。Storage の build に、設定の配列を渡します。

php
use Illuminate\Support\Facades\Storage;

$disk = Storage::build([
    'driver' => 'local',
    'root' => '/path/to/root',
]);

$disk->put('image.jpg', $content);

ファイルを取り出す#

get で、ファイルの中身を取り出せます。ファイルの文字列そのままが返ります。道すじは、ディスクの「root」からの相対の場所で書くことを忘れないでください。

php
$contents = Storage::get('file.jpg');

ファイルの中身が JSON(データを文字で表す形式)なら、json で、読んで配列などに直せます。

php
$orders = Storage::json('orders.json');

ファイルがディスクにあるかは exists で調べます。

php
if (Storage::disk('s3')->exists('file.jpg')) {
    // ...
}

ファイルがディスクに無いかは missing で調べます。

php
if (Storage::disk('s3')->missing('file.jpg')) {
    // ...
}

ダウンロードさせる#

download は、ユーザーのブラウザに、ファイルを強制的にダウンロードさせるレスポンスを作ります。2つ目の引数にファイル名を渡すと、ダウンロードする人に見えるファイル名になります。3つ目の引数には、HTTP ヘッダー(レスポンスに付く説明書き)の配列を渡せます。

php
return Storage::download('file.jpg');

return Storage::download('file.jpg', $name, $headers);

ファイルの URL#

url で、ファイルの URL を取り出せます。local ドライバーのときは、渡した道すじの前に /storage を付けた、相対の URL が返ります。s3 ドライバーのときは、外のサーバーの完全な URL が返ります。

php
use Illuminate\Support\Facades\Storage;

$url = Storage::url('file.jpg');

local ドライバーで、だれでも見られるようにしたいファイルは、storage/app/public フォルダに置きます。そして、public/storage に、storage/app/public を指すシンボリックリンクを作ります(上の「public ディスク」を見る)。

注意

local ドライバーでは、url が返す値は、URL エンコード(URL に使えない文字の書き換え)がされていません。そのため、いつも、正しい URL になるファイル名で保存することをお勧めします。

URL のホストを変える#

Storage で作る URL のホスト(サーバーの名前の部分)を変えたいときは、ディスクの設定の url を足すか、変えます。

php
'public' => [
    'driver' => 'local',
    'root' => storage_path('app/public'),
    'url' => env('APP_URL').'/storage',
    'visibility' => 'public',
    'throw' => false,
],

期限つきの URL#

temporaryUrl で、local や s3 ドライバーのファイルに、期限つきの URL を作れます。道すじと、URL がいつまで使えるかを表す DateTime を渡します。

php
use Illuminate\Support\Facades\Storage;

$url = Storage::temporaryUrl(
    'file.jpg', now()->plus(minutes: 5)
);

local の期限つき URL を有効にする#

local ドライバーに期限つき URL の機能が入る前からアプリを作っているときは、local の期限つき URL を有効にする必要があるかもしれません。config/filesystems.php の local ディスクの設定に、serve を足します。

php
'local' => [
    'driver' => 'local',
    'root' => storage_path('app/private'),
    'serve' => true, // この行を足す
    'throw' => false,
],

S3 のリクエストのパラメータ#

S3 のリクエストのパラメータ(追加の指定)を足したいときは、パラメータの配列を、temporaryUrl の3つ目の引数に渡します。

php
$url = Storage::temporaryUrl(
    'file.jpg',
    now()->plus(minutes: 5),
    [
        'ResponseContentType' => 'application/octet-stream',
        'ResponseContentDisposition' => 'attachment; filename=file2.jpg',
    ]
);

期限つき URL の作り方を変える#

決まったディスクで、期限つき URL の作り方を変えたいときは、buildTemporaryUrlsUsing を使います。たとえば、ふつうは期限つき URL に対応していないディスクのファイルを、コントローラーからダウンロードさせたいときに役に立ちます。ふつうは、サービスプロバイダ(アプリの起動のときに、道具を登録する場所)の boot メソッドから呼びます。

php
<?php

namespace App\Providers;

use DateTime;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Storage::disk('local')->buildTemporaryUrlsUsing(
            function (string $path, DateTime $expiration, array $options) {
                return URL::temporarySignedRoute(
                    'files.download',
                    $expiration,
                    array_merge($options, ['path' => $path])
                );
            }
        );
    }
}

期限つきのアップロード用 URL#

注意

期限つきのアップロード用 URL を作れるのは、s3 と local ドライバーだけです。

ユーザーのブラウザ側のアプリから、ファイルを直接アップロードするための期限つき URL がほしいときは、temporaryUploadUrl を使います。道すじと、URL がいつまで使えるかを表す DateTime を渡します。連想配列(名前と値の組の並び)が返るので、アップロード用の URL と、アップロードのリクエストに付けるヘッダーに分けて受け取れます。

php
use Illuminate\Support\Facades\Storage;

['url' => $url, 'headers' => $headers] = Storage::temporaryUploadUrl(
    'file.jpg', now()->plus(minutes: 5)
);

この方法は、サーバーレス(自分でサーバーを持たず、必要なときだけプログラムを動かすしくみ)の環境で、特に役に立ちます。そうした環境では、ブラウザ側のアプリから、Amazon S3 のようなクラウドへ、ファイルを直接アップロードする必要があるからです。

ファイルの情報#

ファイルを読み書きするだけでなく、ファイルそのものの情報も取り出せます。たとえば、size で、ファイルの大きさをバイト数で取り出せます。

php
use Illuminate\Support\Facades\Storage;

$size = Storage::size('file.jpg');

lastModified は、ファイルが最後に変えられた時刻を、UNIX タイムスタンプ(1970年1月1日からの秒数)で返します。

php
$time = Storage::lastModified('file.jpg');

ファイルの MIME タイプ(ファイルの種類を表す名前)は、mimeType で取り出せます。

php
$mime = Storage::mimeType('file.jpg');

ファイルの道すじ#

path で、ファイルの道すじを取り出せます。local ドライバーでは、ファイルの絶対パス(一番上のフォルダからの完全な道すじ)が返ります。s3 ドライバーでは、S3 のバケット(ファイルを入れる入れ物)の中での相対の道すじが返ります。

php
use Illuminate\Support\Facades\Storage;

$path = Storage::path('file.jpg');

ファイルを保存する#

put で、ファイルの中身をディスクに保存します。PHP の resource(ファイルなどを指す値)も渡せます。そのときは、Flysystem のストリーム(少しずつ読み書きする方式)が使われます。道すじは、ディスクの「root」からの相対の場所で書くことを忘れないでください。

php
use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents);

Storage::put('file.jpg', $resource);

書きこみに失敗したとき#

put(や、ほかの「書きこみ」の操作)がファイルをディスクに書けないと、false が返ります。

php
if (! Storage::put('file.jpg', $contents)) {
    // ファイルをディスクに書けなかった...
}

ディスクの設定に throw を決めておくこともできます。true にすると、put などの書きこみのメソッドが失敗したとき、League\Flysystem\UnableToWriteFile の例外が出ます。

php
'public' => [
    'driver' => 'local',
    // ...
    'throw' => true,
],

代わりに、ディスクの設定に report を決めることもできます。true にすると、書きこみに失敗しても例外は出ず、書きこみのメソッドが返す値も変わりません。その代わり、Laravel がアプリの例外の処理を使って、元の例外を記録します。

php
'public' => [
    'driver' => 'local',
    // ...
    'report' => true,
],

throw も report も決めていないと、ディスクは、失敗したとき何も言わずに false を返します。元の例外は、出ることも、記録されることもありません。

ファイルの先頭や終わりに足す#

prepend と append で、ファイルの先頭や終わりに文字を足せます。

php
Storage::prepend('file.log', 'Prepended Text');

Storage::append('file.log', 'Appended Text');

ファイルのコピーと移動#

copy で、すでにあるファイルを、ディスクの新しい場所にコピーできます。move で、ファイルの名前を変えたり、新しい場所に移したりできます。

php
Storage::copy('old/file.jpg', 'new/file.jpg');

Storage::move('old/file.jpg', 'new/file.jpg');

copyToDisk と moveToDisk で、ファイルをほかのディスクにコピー・移動できます。3つ目の引数を渡さないかぎり、元のファイルの道すじが、移した先のディスクでも使われます。

php
Storage::disk('local')->copyToDisk('s3', 'reports/report.csv');

Storage::disk('local')->moveToDisk(
    's3', 'reports/report.csv', 'archive/report.csv'
);

自動のストリーミング#

ファイルをストリーム(少しずつ送る方式)で保存すると、メモリの使い方が大きく減ります。ファイルのストリーミングを Laravel にまかせたいときは、putFile か putFileAs を使います。Illuminate\Http\File か Illuminate\Http\UploadedFile を渡すと、自動で、ほしい場所にストリームで保存されます。

php
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;

// ファイル名のために、ほかとかぶらない ID を自動で作る...
$path = Storage::putFile('photos', new File('/path/to/photo'));

// ファイル名を自分で決める...
$path = Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');

putFile には、知っておくべきことがいくつかあります。まず、フォルダの名前だけを書き、ファイル名は書いていません。ふつう、putFile は、ファイル名として、ほかとかぶらない ID を作ります。ファイルの拡張子は、MIME タイプを調べて決めます。putFile は、ファイルの道すじを返します。そのため、作られたファイル名を含む道すじを、データベースに保存できます。

putFile と putFileAs には、保存したファイルの「公開の度合い」(visibility)を決める引数もあります。Amazon S3 のようなクラウドのディスクに保存して、作った URL でだれでも見られるようにしたいときに、特に役に立ちます。

php
Storage::putFile('photos', new File('/path/to/photo'), 'public');

ファイルのアップロード#

Web アプリでファイルを保存する場面でいちばん多いのは、写真や書類など、ユーザーがアップロードしたファイルを保存することです。アップロードされたファイルの store を使うと、とても簡単に保存できます。保存したい道すじを渡して store を呼びます。

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserAvatarController extends Controller
{
    /**
     * Update the avatar for the user.
     */
    public function update(Request $request): string
    {
        $path = $request->file('avatar')->store('avatars');

        return $path;
    }
}

この例には、知っておくべきことがあります。フォルダの名前だけを書き、ファイル名は書いていません。ふつう、store は、ファイル名として、ほかとかぶらない ID を作ります。ファイルの拡張子は、MIME タイプを調べて決めます。store は、ファイルの道すじを返します。そのため、作られたファイル名を含む道すじを、データベースに保存できます。

Storage の putFile でも、上の例と同じ保存ができます。

php
$path = Storage::putFile('avatars', $request->file('avatar'));

ファイル名を決める#

ファイル名を自動でつけてほしくないときは、storeAs を使います。道すじ・ファイル名・(なくてもよい)ディスクを引数に受け取ります。

php
$path = $request->file('avatar')->storeAs(
    'avatars', $request->user()->id
);

Storage の putFileAs でも、上の例と同じ保存ができます。

php
$path = Storage::putFileAs(
    'avatars', $request->file('avatar'), $request->user()->id
);

注意

表示できない文字や、正しくない Unicode の文字は、ファイルの道すじから自動で取りのぞかれます。そのため、Laravel のファイル保存のメソッドに渡す前に、道すじをきれいにしておくとよいでしょう。ファイルの道すじは、League\Flysystem\WhitespacePathNormalizer::normalizePath で整えられます。

ディスクを決める#

アップロードされたファイルの store は、ふつう、標準のディスクを使います。ほかのディスクを使いたいときは、store の2つ目の引数に、ディスクの名前を渡します。

php
$path = $request->file('avatar')->store(
    'avatars/'.$request->user()->id, 's3'
);

storeAs では、ディスクの名前を3つ目の引数に渡します。

php
$path = $request->file('avatar')->storeAs(
    'avatars',
    $request->user()->id,
    's3'
);

アップロードされたファイルのそのほかの情報#

アップロードされたファイルの元の名前と拡張子がほしいときは、getClientOriginalName と getClientOriginalExtension が使えます。

php
$file = $request->file('avatar');

$name = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();

ただし、getClientOriginalName と getClientOriginalExtension は、安全でないとされています。悪意のあるユーザーが、ファイル名や拡張子を書きかえられるからです。そのため、ふつうは、hashName と extension を使って、名前と拡張子を決めるほうがよいです。

php
$file = $request->file('avatar');

$name = $file->hashName(); // ほかとかぶらない、ランダムな名前を作る...
$extension = $file->extension(); // ファイルの MIME タイプから拡張子を決める...

ファイルの公開の度合い(visibility)#

Laravel の Flysystem では、「visibility」は、いろいろな OS のファイルの権限(だれが読み書きしてよいか)を、まとめて表すものです。ファイルは、public(公開)か private(非公開)のどちらかにできます。public にしたファイルは、一般に、ほかの人も見られるものとされます。たとえば、S3 ドライバーでは、public のファイルの URL を取り出せます。

ファイルを書くとき、put で公開の度合いも決められます。

php
use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents, 'public');

すでに保存したファイルは、getVisibility で公開の度合いを調べ、setVisibility で変えられます。

php
$visibility = Storage::getVisibility('file.jpg');

Storage::setVisibility('file.jpg', 'public');

アップロードされたファイルを public で保存するには、storePublicly と storePubliclyAs が使えます。

php
$path = $request->file('avatar')->storePublicly('avatars', 's3');

$path = $request->file('avatar')->storePubliclyAs(
    'avatars',
    $request->user()->id,
    's3'
);

画像を加工する#

アップロードされた画像を、保存する前に、小さくしたり、切り取ったり、形式を変えたりしたいときは、Laravel の画像の加工の機能が使えます。

php
$path = $request->image('avatar')
    ->cover(400, 400)
    ->toWebp()
    ->storePublicly('avatars', 'public');

ファイルのディスクにすでに保存してあるファイルからも、画像のオブジェクトを作れます。

php
$image = Storage::disk('public')->image('avatars/photo.jpg');

local のファイルと公開の度合い#

local ドライバーでは、public は、フォルダには 0755、ファイルには 0644 の権限(だれが読み書きしてよいかを表す数字)になります。この対応は、アプリの filesystems 設定で変えられます。

php
'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
    'permissions' => [
        'file' => [
            'public' => 0644,
            'private' => 0600,
        ],
        'dir' => [
            'public' => 0755,
            'private' => 0700,
        ],
    ],
    'throw' => false,
],

ファイルを消す#

delete は、ファイル名1つか、ファイル名の配列を受け取って消します。

php
use Illuminate\Support\Facades\Storage;

Storage::delete('file.jpg');

Storage::delete(['file.jpg', 'file2.jpg']);

必要なら、ファイルを消すディスクも決められます。

php
use Illuminate\Support\Facades\Storage;

Storage::disk('s3')->delete('path/file.jpg');

フォルダの操作#

フォルダの中のファイルをすべて取り出す#

files は、決めたフォルダの中のファイルをすべて、配列で返します。サブフォルダの中も含めたファイルの一覧がほしいときは、allFiles を使います。

php
use Illuminate\Support\Facades\Storage;

$files = Storage::files($directory);

$files = Storage::allFiles($directory);

フォルダの中のフォルダをすべて取り出す#

directories は、決めたフォルダの中のフォルダをすべて、配列で返します。サブフォルダの中も含めたフォルダの一覧がほしいときは、allDirectories を使います。

php
$directories = Storage::directories($directory);

$directories = Storage::allDirectories($directory);

フォルダを作る#

makeDirectory は、決めたフォルダを、必要なサブフォルダも含めて作ります。

php
Storage::makeDirectory($directory);

フォルダを消す#

deleteDirectory は、フォルダと、その中のすべてのファイルを消します。

php
Storage::deleteDirectory($directory);

ファイルの保存のテスト#

Storage の fake を使うと、にせもののディスクを簡単に作れます。Illuminate\Http\UploadedFile が作るにせのファイルと組み合わせると、ファイルのアップロードのテストが、ぐっと楽になります。たとえば、次のように書きます。

php
<?php

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

test('albums can be uploaded', function () {
    Storage::fake('photos');

    $response = $this->json('POST', '/photos', [
        UploadedFile::fake()->image('photo1.jpg'),
        UploadedFile::fake()->image('photo2.jpg')
    ]);

    // 1つ以上のファイルが保存されたことを確かめる
    Storage::disk('photos')->assertExists('photo1.jpg');
    Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);

    // 1つ以上のファイルが保存されていないことを確かめる
    Storage::disk('photos')->assertMissing('missing.jpg');
    Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);

    // 決めたフォルダの中のファイルの数が、期待した数であることを確かめる
    Storage::disk('photos')->assertCount('/wallpapers', 2);

    // 決めたフォルダが空であることを確かめる
    Storage::disk('photos')->assertDirectoryEmpty('/wallpapers');

    // ディスクにファイルが1つも無いことを確かめる
    Storage::disk('photos')->assertEmpty();
});

PHPUnit で書くとき:

php
<?php

namespace Tests\Feature;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_albums_can_be_uploaded(): void
    {
        Storage::fake('photos');

        $response = $this->json('POST', '/photos', [
            UploadedFile::fake()->image('photo1.jpg'),
            UploadedFile::fake()->image('photo2.jpg')
        ]);

        // 1つ以上のファイルが保存されたことを確かめる
        Storage::disk('photos')->assertExists('photo1.jpg');
        Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);

        // 1つ以上のファイルが保存されていないことを確かめる
        Storage::disk('photos')->assertMissing('missing.jpg');
        Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);

        // 決めたフォルダの中のファイルの数が、期待した数であることを確かめる
        Storage::disk('photos')->assertCount('/wallpapers', 2);

        // 決めたフォルダが空であることを確かめる
        Storage::disk('photos')->assertDirectoryEmpty('/wallpapers');

        // ディスクにファイルが1つも無いことを確かめる
        Storage::disk('photos')->assertEmpty();
    }
}
命令 説明
assertExists 渡したファイル(またはファイルの配列)が保存されている
assertMissing 渡したファイル(またはファイルの配列)が保存されていない
assertCount 決めたフォルダの中のファイルの数が、期待した数である
assertDirectoryEmpty 決めたフォルダが空である
assertEmpty ディスクにファイルが1つも無い

ふつう、fake は、一時的なフォルダの中のファイルをすべて消します。ファイルを残したいときは、代わりに persistentFake を使います。ファイルのアップロードのテストのくわしいことは、HTTP テストの、ファイルのアップロードの節を見てください。

注意

image メソッドには、GD 拡張(PHP で画像を扱う部品)が必要です。

独自のファイル置き場を作る#

Laravel の Flysystem は、はじめから、いくつかの「ドライバー」に対応しています。ただし、Flysystem は、それだけに限られず、ほかの多くのファイル置き場のアダプター(つなぎ役)も持っています。そうしたアダプターを Laravel のアプリで使いたいときは、独自のドライバーを作れます。

独自のファイル置き場を作るには、Flysystem のアダプターが必要です。ここでは、コミュニティが作った Dropbox のアダプターを、プロジェクトに足してみます。

bash
composer require spatie/flysystem-dropbox

次に、アプリのサービスプロバイダの boot メソッドの中で、ドライバーを登録します。Storage の extend を使います。

php
<?php

namespace App\Providers;

use Illuminate\Contracts\Foundation\Application;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Storage::extend('dropbox', function (Application $app, array $config) {
            $adapter = new DropboxAdapter(new DropboxClient(
                $config['authorization_token']
            ));

            return new FilesystemAdapter(
                new Filesystem($adapter, $config),
                $adapter,
                $config
            );
        });
    }
}

extend の1つ目の引数はドライバーの名前、2つ目の引数は、$app と $config を受け取るクロージャ(名前のない関数)です。クロージャは、Illuminate\Filesystem\FilesystemAdapter を返さなければなりません。$config には、そのディスクについて config/filesystems.php に書いた値が入っています。

拡張のサービスプロバイダを作って登録したら、config/filesystems.php で dropbox ドライバーが使えるようになります。

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧