Laravelで画像のアップロードと削除を実装してみる

地獄からの使者、スパイダーマッ!
ということで9/7(金)にスパイダーマンのゲーム(PS4)が発売されましたね。
スパイダーマンになった気分になれるゲームでめちゃくちゃ面白いです。
f:id:hand28:20180927112443j:plain
f:id:hand28:20180927112452j:plain

Marvel's Spider-Man move

Marvel's Spider-Man action

移動もアクションも爽快で止め時がわからなくなります。

けれど、このUIが分かりにくくてここだけマイナスポイントです。
f:id:hand28:20180927130545j:plain
「続ける」も「リトライ」も今プレイしているモードをやり直して続けると捉えられるので、一瞬考える時間が生まれてしまうのが良くないかな〜っと思ったり思わなかったり(エンジニア脳)。

そろそろトロコンしそうなのでクリアしたら冬に発売されるKH3に向けて、キングダムハーツHD1.5+2.5リミックスをプレイしていこうと思ってます。

==========================================

さて、本題に。
Laravelで画像のアップロードと削除を実装してみます。筆者の環境ではLaravelのバージョンは5.5です。
仕様としては画像が既にアップロードされている場合に更に画像をアップロードする場合は、既にアップロードされている画像を削除するようにしています。

画像のアップロードに関してはこちらを元に実装しています。
Laravelで画像ファイルアップロードをする簡単なサンプル


フォームの作成
画像をアップロードするフォームを作成します。
基本的には参考にした記事通りですが、削除ボタンが追加されています。
元記事と同じくresources/views/home.blade.phpに記述していきます。

{!! Form::open(['url' => '/upload', 'method' => 'post', 'files' => true]) !!}
@if (session('success'))
    <div class="alert alert-success">{{ session('success') }}</div>
@endif
@if($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach($errors->all() as $error)
            <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<div class="form-group">
    @if($user->avatar_filename)
    <p>
        <img src="{{ asset('storage/avatar/' .$user->avatar_filename) }}" alt="avater" />
    </p>
    @endif
    {!! Form::label('file', '画像アップロード', ['class' => 'control-label']) !!}
    {!! Form::file('file') !!}
</div>
<div class="form-group">
    {!! Form::submit('アップロード', ['class' => 'btn btn-default']) !!}
</div>
{!! Form::close() !!}

//元記事からの追加点、削除ボタンを追加しています。
{!! Form::open(['url' => '/delete', 'method' => 'post']) !!}
{{ method_field('DELETE') }}
    <button class="btn btn-danger">削除</button>
{!! Form::close() !!}   


Routeを追加
uploadの他にdeleteも追加します。routes/web.phpに記述していきます。

Route::post('/upload', 'HomeController@upload');
Route::delete('/delete', 'HomeController@delete');

Controllerに記述
画像のアップロードと削除の機能を実装していきます。

public function upload(Request $request)
    {
        $this->validate($request, [
            'file' => [
                'required', 'file', 'mimes:jpeg,png'
            ]
        ]);
        if ($request->file('file')->isValid([])) {
            $filename = $request->file->store('public/avatar');
            $user = User::find(auth()->id());
    //画像アップロード時に既に他の画像がアップロードされている場合に既存の画像を削除する処理
            Storage::disk('local')->delete('public/avatar/'.$user->avatar_filename);

            $user->avatar_filename = basename($filename);
            $user->save();

            return redirect('/home')->with('success', '保存しました');
        } else {
            return redirect()->back()->withInput()->witherrors(['file' => '画像がアップロードされてないか不正なデータです。']);
        }
    }

    public function delete(Request $request)
    {
        $user = User::find(auth()->id());
        //ファイルがアップロードされてない場合に削除ボタンをクリックした時の挙動を制御
        if (is_null($user->avatar_filename)) {
            return redirect('/home')->with('error', '削除するファイルがありません');
        }
        Storage::disk('local')->delete('public/avatar/'.$user->avatar_filename);
        $user->avatar_filename = null;
        $user->save();
        return redirect('/home')->with('success', '削除しました');
    }


実装時の挙動の動画を載せようと思いましたが、時間がないので割愛します。

基本的な画像のアップロードと削除はできましたが、今時のUIだと画像を選択するとアップロードする前に選択した画像が表示されるのが当たり前だと思うので、そちらの方もいつかはやってみたいかなとは思っています。

いずれまた一つ頼もう