ファイルの保存(ストレージ)
ファイルを保存・取り出し・削除する 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 に書きこみます。
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 コマンドで作れます。
php artisan storage:link
ファイルを保存し、リンクも作ったら、asset ヘルパー関数で、そのファイルの URL を作れます。
echo asset('storage/file.txt');
filesystems 設定には、シンボリックリンクをさらに足せます。storage:link を動かすと、設定したリンクがすべて作られます。
'links' => [
public_path('storage') => storage_path('app/public'),
public_path('images') => storage_path('app/images'),
],
作ったリンクを消すには、storage:unlink を使います。
php artisan storage:unlink
ドライバーごとの準備#
S3 ドライバーの設定#
S3 ドライバーを使う前に、Composer で Flysystem の S3 パッケージを入れます。
composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies
config/filesystems.php には、S3 のディスクの設定が入っています。ふつうは、S3 の情報や認証の情報を、次の環境変数(.env に書く設定値)に書きます。設定ファイルが、この環境変数を読みます。
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 パッケージを入れます。
composer require league/flysystem-ftp "^3.0"
Laravel は FTP にも対応していますが、標準の config/filesystems.php には見本が入っていません。FTP のディスクを作りたいときは、次の設定の例が使えます。
'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 パッケージを入れます。
composer require league/flysystem-sftp-v3 "^3.0"
SFTP も、標準の設定ファイルに見本が入っていません。SFTP のディスクを作りたいときは、次の設定の例が使えます。
'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 パッケージを入れます。
composer require league/flysystem-path-prefixing "^3.0"
scoped ドライバーを使うと、すでにあるどのディスクからも、場所を絞ったディスクを作れます。たとえば、s3 ディスクのうち、決まった場所の中だけを扱うディスクにできます。そのディスクで扱うファイルは、すべて、決めた場所の中に限られます。
's3-videos' => [
'driver' => 'scoped',
'disk' => 's3',
'prefix' => 'path/to/videos',
],
読み取り専用(read-only)#
「読み取り専用」のディスクは、書きこみができないディスクです。read-only の設定を使う前に、Composer で追加の Flysystem パッケージを入れます。
composer require league/flysystem-read-only "^3.0"
そのうえで、ディスクの設定に read-only を足します。
's3-videos' => [
'driver' => 's3',
// ...
'read-only' => true,
],
読みながら移す(read-through)#
read-through ディスクは、サービスを止めずに、ディスクのあいだでファイルを引っ越すためのものです。ファイルを読むとき、Laravel はまず主のディスクを調べます。ファイルが予備(フォールバック)のディスクにしか無いときは、予備のディスクから読み、次のアクセスのために、主のディスクにコピーします。
'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 環境変数で決めます。
'endpoint' => env('AWS_ENDPOINT', 'https://rustfs:9000'),
ディスクを選ぶ#
設定したどのディスクも、Storage ファサード(:: で呼べる窓口)で扱えます。たとえば、put で、標準のディスクにアバター(プロフィール画像)を保存できます。disk を先に呼ばずに Storage のメソッドを呼ぶと、標準のディスクが使われます。
use Illuminate\Support\Facades\Storage;
Storage::put('avatars/1', $content);
複数のディスクを使うアプリでは、disk で、決まったディスクのファイルを扱えます。
Storage::disk('s3')->put('avatars/1', $content);
その場でディスクを作る#
アプリの filesystems 設定に書いていない設定で、実行中にその場でディスクを作りたいことがあります。Storage の build に、設定の配列を渡します。
use Illuminate\Support\Facades\Storage;
$disk = Storage::build([
'driver' => 'local',
'root' => '/path/to/root',
]);
$disk->put('image.jpg', $content);
ファイルを取り出す#
get で、ファイルの中身を取り出せます。ファイルの文字列そのままが返ります。道すじは、ディスクの「root」からの相対の場所で書くことを忘れないでください。
$contents = Storage::get('file.jpg');
ファイルの中身が JSON(データを文字で表す形式)なら、json で、読んで配列などに直せます。
$orders = Storage::json('orders.json');
ファイルがディスクにあるかは exists で調べます。
if (Storage::disk('s3')->exists('file.jpg')) {
// ...
}
ファイルがディスクに無いかは missing で調べます。
if (Storage::disk('s3')->missing('file.jpg')) {
// ...
}
ダウンロードさせる#
download は、ユーザーのブラウザに、ファイルを強制的にダウンロードさせるレスポンスを作ります。2つ目の引数にファイル名を渡すと、ダウンロードする人に見えるファイル名になります。3つ目の引数には、HTTP ヘッダー(レスポンスに付く説明書き)の配列を渡せます。
return Storage::download('file.jpg');
return Storage::download('file.jpg', $name, $headers);
ファイルの URL#
url で、ファイルの URL を取り出せます。local ドライバーのときは、渡した道すじの前に /storage を付けた、相対の URL が返ります。s3 ドライバーのときは、外のサーバーの完全な URL が返ります。
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 を足すか、変えます。
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],
期限つきの URL#
temporaryUrl で、local や s3 ドライバーのファイルに、期限つきの URL を作れます。道すじと、URL がいつまで使えるかを表す DateTime を渡します。
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 を足します。
'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true, // この行を足す
'throw' => false,
],
S3 のリクエストのパラメータ#
S3 のリクエストのパラメータ(追加の指定)を足したいときは、パラメータの配列を、temporaryUrl の3つ目の引数に渡します。
$url = Storage::temporaryUrl(
'file.jpg',
now()->plus(minutes: 5),
[
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename=file2.jpg',
]
);
期限つき URL の作り方を変える#
決まったディスクで、期限つき URL の作り方を変えたいときは、buildTemporaryUrlsUsing を使います。たとえば、ふつうは期限つき URL に対応していないディスクのファイルを、コントローラーからダウンロードさせたいときに役に立ちます。ふつうは、サービスプロバイダ(アプリの起動のときに、道具を登録する場所)の boot メソッドから呼びます。
<?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 と、アップロードのリクエストに付けるヘッダーに分けて受け取れます。
use Illuminate\Support\Facades\Storage;
['url' => $url, 'headers' => $headers] = Storage::temporaryUploadUrl(
'file.jpg', now()->plus(minutes: 5)
);
この方法は、サーバーレス(自分でサーバーを持たず、必要なときだけプログラムを動かすしくみ)の環境で、特に役に立ちます。そうした環境では、ブラウザ側のアプリから、Amazon S3 のようなクラウドへ、ファイルを直接アップロードする必要があるからです。
ファイルの情報#
ファイルを読み書きするだけでなく、ファイルそのものの情報も取り出せます。たとえば、size で、ファイルの大きさをバイト数で取り出せます。
use Illuminate\Support\Facades\Storage;
$size = Storage::size('file.jpg');
lastModified は、ファイルが最後に変えられた時刻を、UNIX タイムスタンプ(1970年1月1日からの秒数)で返します。
$time = Storage::lastModified('file.jpg');
ファイルの MIME タイプ(ファイルの種類を表す名前)は、mimeType で取り出せます。
$mime = Storage::mimeType('file.jpg');
ファイルの道すじ#
path で、ファイルの道すじを取り出せます。local ドライバーでは、ファイルの絶対パス(一番上のフォルダからの完全な道すじ)が返ります。s3 ドライバーでは、S3 のバケット(ファイルを入れる入れ物)の中での相対の道すじが返ります。
use Illuminate\Support\Facades\Storage;
$path = Storage::path('file.jpg');
ファイルを保存する#
put で、ファイルの中身をディスクに保存します。PHP の resource(ファイルなどを指す値)も渡せます。そのときは、Flysystem のストリーム(少しずつ読み書きする方式)が使われます。道すじは、ディスクの「root」からの相対の場所で書くことを忘れないでください。
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents);
Storage::put('file.jpg', $resource);
書きこみに失敗したとき#
put(や、ほかの「書きこみ」の操作)がファイルをディスクに書けないと、false が返ります。
if (! Storage::put('file.jpg', $contents)) {
// ファイルをディスクに書けなかった...
}
ディスクの設定に throw を決めておくこともできます。true にすると、put などの書きこみのメソッドが失敗したとき、League\Flysystem\UnableToWriteFile の例外が出ます。
'public' => [
'driver' => 'local',
// ...
'throw' => true,
],
代わりに、ディスクの設定に report を決めることもできます。true にすると、書きこみに失敗しても例外は出ず、書きこみのメソッドが返す値も変わりません。その代わり、Laravel がアプリの例外の処理を使って、元の例外を記録します。
'public' => [
'driver' => 'local',
// ...
'report' => true,
],
throw も report も決めていないと、ディスクは、失敗したとき何も言わずに false を返します。元の例外は、出ることも、記録されることもありません。
ファイルの先頭や終わりに足す#
prepend と append で、ファイルの先頭や終わりに文字を足せます。
Storage::prepend('file.log', 'Prepended Text');
Storage::append('file.log', 'Appended Text');
ファイルのコピーと移動#
copy で、すでにあるファイルを、ディスクの新しい場所にコピーできます。move で、ファイルの名前を変えたり、新しい場所に移したりできます。
Storage::copy('old/file.jpg', 'new/file.jpg');
Storage::move('old/file.jpg', 'new/file.jpg');
copyToDisk と moveToDisk で、ファイルをほかのディスクにコピー・移動できます。3つ目の引数を渡さないかぎり、元のファイルの道すじが、移した先のディスクでも使われます。
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 を渡すと、自動で、ほしい場所にストリームで保存されます。
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 でだれでも見られるようにしたいときに、特に役に立ちます。
Storage::putFile('photos', new File('/path/to/photo'), 'public');
ファイルのアップロード#
Web アプリでファイルを保存する場面でいちばん多いのは、写真や書類など、ユーザーがアップロードしたファイルを保存することです。アップロードされたファイルの store を使うと、とても簡単に保存できます。保存したい道すじを渡して store を呼びます。
<?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 でも、上の例と同じ保存ができます。
$path = Storage::putFile('avatars', $request->file('avatar'));
ファイル名を決める#
ファイル名を自動でつけてほしくないときは、storeAs を使います。道すじ・ファイル名・(なくてもよい)ディスクを引数に受け取ります。
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
Storage の putFileAs でも、上の例と同じ保存ができます。
$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);
注意
表示できない文字や、正しくない Unicode の文字は、ファイルの道すじから自動で取りのぞかれます。そのため、Laravel のファイル保存のメソッドに渡す前に、道すじをきれいにしておくとよいでしょう。ファイルの道すじは、League\Flysystem\WhitespacePathNormalizer::normalizePath で整えられます。
ディスクを決める#
アップロードされたファイルの store は、ふつう、標準のディスクを使います。ほかのディスクを使いたいときは、store の2つ目の引数に、ディスクの名前を渡します。
$path = $request->file('avatar')->store(
'avatars/'.$request->user()->id, 's3'
);
storeAs では、ディスクの名前を3つ目の引数に渡します。
$path = $request->file('avatar')->storeAs(
'avatars',
$request->user()->id,
's3'
);
アップロードされたファイルのそのほかの情報#
アップロードされたファイルの元の名前と拡張子がほしいときは、getClientOriginalName と getClientOriginalExtension が使えます。
$file = $request->file('avatar');
$name = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
ただし、getClientOriginalName と getClientOriginalExtension は、安全でないとされています。悪意のあるユーザーが、ファイル名や拡張子を書きかえられるからです。そのため、ふつうは、hashName と extension を使って、名前と拡張子を決めるほうがよいです。
$file = $request->file('avatar');
$name = $file->hashName(); // ほかとかぶらない、ランダムな名前を作る...
$extension = $file->extension(); // ファイルの MIME タイプから拡張子を決める...
ファイルの公開の度合い(visibility)#
Laravel の Flysystem では、「visibility」は、いろいろな OS のファイルの権限(だれが読み書きしてよいか)を、まとめて表すものです。ファイルは、public(公開)か private(非公開)のどちらかにできます。public にしたファイルは、一般に、ほかの人も見られるものとされます。たとえば、S3 ドライバーでは、public のファイルの URL を取り出せます。
ファイルを書くとき、put で公開の度合いも決められます。
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents, 'public');
すでに保存したファイルは、getVisibility で公開の度合いを調べ、setVisibility で変えられます。
$visibility = Storage::getVisibility('file.jpg');
Storage::setVisibility('file.jpg', 'public');
アップロードされたファイルを public で保存するには、storePublicly と storePubliclyAs が使えます。
$path = $request->file('avatar')->storePublicly('avatars', 's3');
$path = $request->file('avatar')->storePubliclyAs(
'avatars',
$request->user()->id,
's3'
);
画像を加工する#
アップロードされた画像を、保存する前に、小さくしたり、切り取ったり、形式を変えたりしたいときは、Laravel の画像の加工の機能が使えます。
$path = $request->image('avatar')
->cover(400, 400)
->toWebp()
->storePublicly('avatars', 'public');
ファイルのディスクにすでに保存してあるファイルからも、画像のオブジェクトを作れます。
$image = Storage::disk('public')->image('avatars/photo.jpg');
local のファイルと公開の度合い#
local ドライバーでは、public は、フォルダには 0755、ファイルには 0644 の権限(だれが読み書きしてよいかを表す数字)になります。この対応は、アプリの filesystems 設定で変えられます。
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' => [
'file' => [
'public' => 0644,
'private' => 0600,
],
'dir' => [
'public' => 0755,
'private' => 0700,
],
],
'throw' => false,
],
ファイルを消す#
delete は、ファイル名1つか、ファイル名の配列を受け取って消します。
use Illuminate\Support\Facades\Storage;
Storage::delete('file.jpg');
Storage::delete(['file.jpg', 'file2.jpg']);
必要なら、ファイルを消すディスクも決められます。
use Illuminate\Support\Facades\Storage;
Storage::disk('s3')->delete('path/file.jpg');
フォルダの操作#
フォルダの中のファイルをすべて取り出す#
files は、決めたフォルダの中のファイルをすべて、配列で返します。サブフォルダの中も含めたファイルの一覧がほしいときは、allFiles を使います。
use Illuminate\Support\Facades\Storage;
$files = Storage::files($directory);
$files = Storage::allFiles($directory);
フォルダの中のフォルダをすべて取り出す#
directories は、決めたフォルダの中のフォルダをすべて、配列で返します。サブフォルダの中も含めたフォルダの一覧がほしいときは、allDirectories を使います。
$directories = Storage::directories($directory);
$directories = Storage::allDirectories($directory);
フォルダを作る#
makeDirectory は、決めたフォルダを、必要なサブフォルダも含めて作ります。
Storage::makeDirectory($directory);
フォルダを消す#
deleteDirectory は、フォルダと、その中のすべてのファイルを消します。
Storage::deleteDirectory($directory);
ファイルの保存のテスト#
Storage の fake を使うと、にせもののディスクを簡単に作れます。Illuminate\Http\UploadedFile が作るにせのファイルと組み合わせると、ファイルのアップロードのテストが、ぐっと楽になります。たとえば、次のように書きます。
<?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
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 のアダプターを、プロジェクトに足してみます。
composer require spatie/flysystem-dropbox
次に、アプリのサービスプロバイダの boot メソッドの中で、ドライバーを登録します。Storage の extend を使います。
<?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日時点の内容をもとに、日本語でまとめています。