画像のアップロードにかなり手こずってしまいました。
Laravel×Vueの記事が少なかったため、記事にしました。
開発環境
Laravel9
Vue3
Inertia
※コントローラのルートは既に通してあることとします。
※今回の画像のアップロード先はpublic/imagesにします。
今回はプロフィールのEdit(編集画面)を想定しています。
これはLaravelインストール時に予め用意されているUserテーブルと紐づいています。
(カラムは最低限に絞りました。)
テーブル
Profiles
カラム名 | 型 |
---|---|
nick_name | string |
filename | string |
Vue
先にフォームの準備をします。
<template>
<!-- 画像の表示(プレビューは別に作成してください) -->
<div>
<img :src="'/images/' + props.profile.filename">
<input type="hidden" v-model="form.filename">
</div>
<form @submit.prevent="updateTest(form.id)" enctype="multipart/form-data">
<div>
<label for="nick_name">ニックネーム</label>
<input type="text" id="nick_name" name="nick_name" v-model="form.nick_name">
</div>
<div>
<label for="filename">画像</label>
<input id="file" name="file" type="file" @input="form.file = $event.target.files[0]" >
</div>
<button type="submit">更新する</button>
</form>
</template>
画像を扱う際は、enctype="multipart/form-data"が必須です。
inputタグ内で本来ならv-modelを使えますが、画像を扱う際は使えません。
画像で下記のinputタグ用意にしていますが、選択されたファイル名を疑似的に入れて、ユーザーからは見えないようにしています。これでupdate()が行えます。
<input type="hidden" v-model="form.filename">
またコントローラで任意のファイル名を付けたいため、DBのカラム名はfilenameですが、idとnameにはfileとしておきます。
<script setup>
import {router, useForm} from '@inertiajs/vue3';
<!-- DVの値を取得 -->
const props = defineProps({
Profile: Object
})
const form = useForm({
id: props.profile.id,
nick_name: props.profile.nick_name,
filename: props.profile.filename,
file: null
})
<!-- コントローラにフォームの情報を送る -->
const updatePaidMemberDetail = id => {
router.post(route('profile.update', {profile: id}), {
_method: 'put',
nick_name: form.nick_name,
file: form.file,
})
}
</script>
コントローラー
public function update(ProfileRequest $request, $id)
{
$profile = profile::findOrFail($id);
$fname = $request->file('file')->getClientOriginalExtension();
$disk = Storage::build([
'driver' => 'local',
'root' => public_path('images'),
]);
$random_name = Str::random(15);
$hoge = date('Y-m-d') . $random_name . '.' . $fname;
$disk->putFileAs('', $request->file('file'), $hoge);
$profilel->nick_name = $request->nick_name;
$profile->filename = $hoge;
$profile->save();
return redirect()->route('dashboard');
}
以下、詳細です。
$fname = $request->file('file')->getClientOriginalExtension();
ファイルを取得し、拡張子を取得しています。
$disk = Storage::build([
'driver' => 'local',
'root' => public_path('images'),
]);
オンデマンドディスクです。アプリケーションのfilesystems設定ファイルに実際にその構成が存在しなくても、指定する構成を使用して実行時にディスクを作成します。
$random_name = Str::random(15);
$hoge = date('Y-m-d') . $random_name . '.' . $fname;
ランダムで15文字の名前を生成しました。
今回は、今日の日付 + ランダムの名前 + 拡張子 としてファイル名を付けます。
$disk->putFileAs('', $request->file('file'), $hoge);
putFileAs()で任意の名前をつけます。
$profilel->nick_name = $request->nick_name;
$profile->filename = $hoge;
$profile->save();
ここでDBに格納して終わりです。
他に参考になる記事を貼っておきます。