FormRequestとサービスコンテナを使って画像アップロード
ファイルに関係するやつ
config/filesystems.phpにファイルシステム設定ファイルがある。
ここで、全てのファイルシステム(=ディスク)を設定できる
このうちの一つに、webに公開してアクセスできるようにするpublicディスクがある。
- ファイルシステムでは、ファイルをstorage/app/public/ディレクトリに保存する。
- ブラウザでは、ファイルを探すときはpublic/strageを見る (storage/app~は探さない見れない)
- ブラウザからはstorage/app/public/にアクセスできないので、シンボリックリンクを作成する
- public/strageにも同じ画像を保存できるようになる
- ブラウザからファイルの読み取りができる
./vendor/bin/sail artisan storage:link
出る→ INFO The [public/storage] link has been connected to [storage/app/public].
echo asset('storage/file_name');で見ると画像が見れる
ファイルのアップロード
name属性で、ファイルのデータをコントローラーに投げることができる。
(inputタグにname属性値を指定すると、ファイルのインスタンスオブジェクトが得られる)
name="icon" を追っていく
view
// route関数は指定した名前付きルートのURLを作成する
<form action="{{ route('account.icon') }}" method="post" enctype="multipart/form-data">
<div class="position-relative">
@csrf
<label for="formFile" class="form-label col-sm-2 "></label>
<div class="position-absolute top-100 start-50 translate-middle col-sm-5">
<input class="form-control" type="file" id="formFile" name="icon">
<button type="submit" class="btn btn-primary col-sm-12">Upload</button>
</div>
</div>
</form>
Controller
namespace App\Http\Controllers\Account;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\Account\IconRequest;
use App\Services\AccountService;
class IconController extends Controller
{
public function __invoke(IconRequest $request, AccountService $accountService)
{
$accountService->saveIcon(Auth::User()->id, $request->icon());
return redirect()
->route('account');
}
}
Account/Iconコントローラーには、IconRequestから分かるようにRequestFormを設定している。
あと、AccountService $accountServiceでサービスコンテナも使ってる
routeからコントローラーにパスされる
→ コントローラーのRequestクラスにパス
→ FormRequestでバリデーション確認
→ コントローラーの処理
→ 処理中にサービスコンテナの関数使用
FormRequest
namespace App\Http\Requests\Account;
use Illuminate\Foundation\Http\FormRequest;
class IconRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
// ↓以外のタイプのファイルが来たらバリデーションされる
return [
'icon' => 'required|image|mimes:jpeg,jpg,png|max:2048',
];
}
//画像を取得
public function icon()
{
return $this->file('icon');
}
}
icon()関数のfile('icon')← name属性のファイルデータが入る!
Service
namespace App\Services;
use Illuminate\Support\Facades\Storage;
use App\Models\User;
class AccountService
{
public function saveIcon(int $userId, $icon)
{
Storage::putFile('public/images', $icon);
$user = User::find($userId);
$user->icon_file_name = $icon->hashName();
$user->save();
}
}
putFileメソッドでは、ファイル名ではなくディレクトリ名のみを指定する。
このメソッドは、Illuminate\Http\File
か、Illuminate\Http\UploadedFile
インスタンスのどっちかを引数に取って、ファイルを自動で保存&渡してくれる
引数の$iconには、name属性で渡したiconが入る!
public function __invoke(IconRequest $request, AccountService $accountService)
{
$accountService->saveIcon(Auth::User()->id, $request->icon());
$request->icon()には、サイズや登録時間などたくさんの情報が入っている。 $icon->hashName()で、その情報中の#hashName: "onI1NthUwkj5b9ctl9oTYEgDSxjS0a6RKi8CcNO3"
をとることができる
->DBに保存される名前として利用
違うのだけど別の書き方
- file&storeメソッド = Storage::putFileメソッド
public function saveFile($file, $tweet)
{
$file_name = $file->getClientOriginalName();
$file->storeAs('public/images', $file_name);
$tweet->filename = $file_name;
}
Discussion