Laravelファイルストレージ 保存用のメソッドについて

# はじめに
この記事ではLaravelのファイル保存用メソッドの使い方や違いについて書いています。
公式ドキュメントを参考にしています。

https://readouble.com/laravel/10.x/ja/filesystem.html

# 各メソッドについて
以下のメソッドについて説明しています。
1. $request->file()->store()
1. $request->file()->storeAs()
1. Storage::put()
1. Storage::putFile()
1. Storage::putFileAs()

## $request->file()->store()
`file()`の引数にはキー名、`store()`の引数には保存先のディレクトリ名を入れます。`file`の引数に入れるのはフォームの`input`に設定した`name`の値です。
```php
use Illuminate\Http\Request;

public function upload(Request $request)
{
    $path = $request->file('example_image')->store('test');
    print_r($path); // test/{ファイル名}.{拡張子}
}
```
上記の例では`プロジェクトディレクトリ/storage/app/test/{ファイル名}`のように保存されます。この保存先はデフォルトで使用するディスクが`local`の場合のものです。ここより後の例も同様です。

ファイル名は`$file->hashName()`で出力されるものと同じで、自動的に設定されます。
```php
public function upload(Request $request)
{
  $file = $request->file('example_image');
  print_r($file->hashName());
}
```
第二引数で`disk`を指定することもできます。
```php
public function upload(Request $request)
{
    $request->file('example_image')->store('test', 'public');
}
```
`プロジェクトディレクトリ/storage/app/public/test/{ファイル名}`のように保存されます。

## $request->file()->storeAs()
`storeAs()`は第一引数、第二引数にそれぞれ「ディレクトリ名」、「ファイル名」を入れます。
```php
use Illuminate\Http\Request;

public function upload(Request $request)
{
  $path = $request->file('example_image')->storeAs('test', 'example_image.png');
  print_r($path); // test/example_image.png
}
```
`プロジェクトディレクトリ/storage/app/test/example_image.png`のように保存されます。
`store()`と同様に第三引数でディスクを指定できます。
```php
storeAs('test', 'example_image.png', 'public');
```

## Storage::put()
ここからは`Storageファザード`のメソッドになります。
`put()`は第一引数に保存先ディレクトリ、第二引数には`Illuminate\Http\UploadedFile`クラスか`Illuminate\Http\File`クラスのインスタンスを入れます。下記の`$file`は`Illuminate\Http\UploadedFile`クラスのインスタンスになります。
```php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

public function upload(Request $request)
{
    $file = $request->file('example_image');
    $path = Storage::put('test', $file);
    print_r($path); // test/{フォルダ名}.{拡張子}
}
```
先ほど説明した`store()`と同じ動作になります。つまり`プロジェクトディレクトリ/storage/app/test/{ファイル名}`のようにファイルが保存され、ファイル名は`$file->hashName()`で取得できるものと同じです。
```php
$request->file('example_image')->store('test')
```

下記のようにディスクの指定することもできます。
```php
public function upload(Request $request)
{
  $file = $request->file('example_image');
  Storage::disk('public')->put('test', $file);
}
```

## Storage::putFile()
`Storage::put()`とほぼ同じになります。
```php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

public function upload(Request $request)
{
  $file = $request->file('example_image');
  $path = Storage::putFile('test', $file);
  print_r($path); // test/{ファイル名}
}
```
`Storage::put()`との違いは保存するまで過程です。`Storage::put()`が一度メモリを経由して保存されるのに対して、こちらはファイルを直接保存します。`Storage::putFile()`はメモリを節約できるため、容量が大きいファイルを保存する際に推奨されるようです。ちなみにこの直接保存する方法をドキュメントでは「自動ストリーミング」と呼んでいました。
自動ストリーミングについては下記を参考にしました。

https://teratail.com/questions/276345

https://laracasts.com/discuss/channels/laravel/storageput-vs-storageputfile

https://www.reddit.com/r/laravel/comments/g70jfr/understanding_use_cases_of_storing_files/


## Storage::putFileAs()
`$request->file()->storeAs()`と同じような動作になります。
```php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

public function index(Request $request)
{
  $file = $request->file('example_image');
  $path = Storage::putFileAs('test', $file, 'example_image.png');
  print_r($path); // test/example_image.png
}
```
`プロジェクトディレクトリ/storage/app/test/example_image.png`のように保存されます。

# 参考

https://readouble.com/laravel/10.x/ja/filesystem.html

https://www.php.net/manual/ja/function.file-put-contents.php

https://teratail.com/questions/276345

https://www.reddit.com/r/laravel/comments/g70jfr/understanding_use_cases_of_storing_files/