6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel/Vue】画像アップロード&DBへ保存

Last updated at Posted at 2023-05-19

画像のアップロードにかなり手こずってしまいました。
Laravel×Vueの記事が少なかったため、記事にしました。

開発環境

Laravel9
Vue3
Inertia

※コントローラのルートは既に通してあることとします。
※今回の画像のアップロード先はpublic/imagesにします。

今回はプロフィールのEdit(編集画面)を想定しています。
これはLaravelインストール時に予め用意されているUserテーブルと紐づいています。
(カラムは最低限に絞りました。)

テーブル

Profiles

カラム名
nick_name string
filename string

Vue

先にフォームの準備をします。

Edit.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としておきます。

Edit.vue
<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>

コントローラー

ProfileController.php
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に格納して終わりです。

他に参考になる記事を貼っておきます。

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?