LoginSignup
6
4

More than 3 years have passed since last update.

Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part6

Last updated at Posted at 2020-03-18

前回のパート

前回はログアウト機能の実装を行いました
前回で認証まわりの実装が終わったので、今パートからはTodo機能の実装に入っていきます
前回のパートはこちらVue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part5

Todoリストの機能

まず、今回のTodoリストの機能をおさらいしておきます
Todoリストの実装する機能は下記の4点になります
削除や新規作成の際などにアニメーションは付けないシンプルなものになっていますので
アニメーションが欲しい方は、一通り実装が終わった際に自身で挑戦してみてください

  • todoの一覧表示
  • todoの新規追加
  • todoの更新
  • todoの削除(完了時)

それでは、上記の4点の実装を行っていきます
まず最初に新規Todoの追加機能の実装から入ります

Laravel側の実装

まずはコントローラーの作成を行います
上記の機能で確認した通り、表示,追加,更新,削除の機能なので
Todo専用の一つのコントローラーである
リソースコントローラーを作成しそれを利用していきます

コマンドにて下記を実行しコントローラーの作成を行ってください
$ php artisan make:controller TodoController --resource
実行で作成されるのが下記のファイルになっているかと思います

TodoController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Todo;
use Log;

class TodoController extends Controller
{
    public function index()
    {
        //
    }

    public function create()
    {
        //
    }

    public function store(Request $request)
    {
        //
    }

    public function show($id)
    {
        //
    }

    public function edit($id)
    {
        //
    }

    public function update(Request $request, $id)
    {
        //
    }

    public function destroy($id)
    {
        //
    }
}

リソースコントローラーについて、わからない方はこちらを参照ください→こちら

これで、Todoに関する全ての処理を行うコントローラーの作成が終わりました
次にapi.phpに作成したリソースフルコントローラーのルートを定義します
api.phpを開いて下記を追加してください

api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::post('/register', 'Auth\RegisterController@register')->name('register');
Route::post('/login', 'Auth\LoginController@login')->name('login');
Route::post('/logout', 'Auth\LoginController@logout')->name('logout');
Route::get('/user', function(){
    return Auth::user();
});
Route::resource('/todo', 'TodoController');    //追加

もう少しLaravel側での実装がありますが
一旦Vue側の実装に移ります

Vue側の実装

それでは次に、Vue側で既に作成したTodo.vueを開きそちらを編集していきます
Todo.vueを開いて下記を追加してください
内容については、一つづ説明していきます

Todo.vue
<template>
    <div>
        <Header />
        <div class="main-container">
            {{ user.name }}のTodoリスト    //・・・①

            <v-text-field v-model="text" label="todo" required></v-text-field>
            <v-btn class="btn" @click="create">登録</v-btn>    //・・・②

            <template v-for="item in items">
                <v-card max-width="450" class="mx-auto" style="marign-top: 10px" :key="item.id">
                    <v-list three-line>
                        <v-list-item :key="item.id">
                            <v-list-item-content>
                                <input type="text" v-model="item.text">    //・・・③
                                <v-btn small>完了</v-btn>
                            </v-list-item-content>
                        </v-list-item>
                    </v-list>
                </v-card>
            </template>
        </div>

    </div>
</template>

<script>
    import Header from './Header';
    import axios from 'axios';

    export default {
        components: {
            Header
        },
        metaInfo: {
            title: 'Todo',
            htmlAttrs: {
                lang: 'ja'
            }
        },
        created () {    //・・・④
            const user = this.$store.getters['auth/user'];
            if (user === null) {
                this.$router.push('/login');
            }
        },
        computed: {
            user() {    //・・・⑤
                return this.$store.getters['auth/user'];
            }
        },
        data () {
            return {
                items: [    //・・・⑥
                    { id: 1, text: 'テスト'},
                    { id: 2, text: 'テスト'}
                ],
                text: ''
            }
        },
        methods: {
            async create() {    //・・・⑦
                await axios.post('/api/todo', { text: this.text });

                axios.get('/api/todo/' + this.user.id)
                .then((res) => {
                    const newItem = res.data.slice(-1)[0];
                    this.items.push(newItem);
                })

                this.text = '';
            },
        }
    }
</script>

<style>
    .main-container {
        width: 500px;
        margin: auto;
    }
    .btn {
        margin-bottom: 20px;
    }
</style>

①は認証ユーザーの情報のVuexで保管してるデータを所得して、ユーザーの名前を表示しています
②クリックイベントでtodoの登録処理のメソッドを発火させます
③今後の機能実装でtodoの内容を表示し書き換えて変更など出来る様に<input>にv-modelで現在のダミーのデータを表示しています
④ログインしているかをチェックしています。ログインしていなければ/loginにリダイレクトされる様にしています
⑤こちらは①でユーザー名を参照するためにcomputedを使ってauth.jsのgetterを利用してstateのuserの情報を所得しています
⑥現在はtodo内容の表示機能がないため、ダミーデータを配置してます
⑦実際のtodoの登録処理のメソッドになります。詳しくは下で話します

⑦のメソッドについて説明します
ここで行っている処理は、フォームに追加したいtodoの内容が入力され登録ボタンが押されると
Laravel側の先ほど定義した/todoに対してPOSTリクエストを送信します
そうすることでLaravelで作成したTodoController.phpstore()アクションが呼び出されます
store()には登録したい内容であるtodoの内容を送ります
それがここの第二引数で指定しています
await axios.post('/api/todo', { text: this.text });
これを受け取ったLaravel側のTodoController.phpstore()アクションがDBに登録処理を行います
その後/todoに対して最新のtodoの情報を所得し
const newItem = res.dataslice(-1)[0]こちらでそのデータの最後(今回登録したデータ)を所得し
this.items.push(newItem)としてitemsに追加してVue側に反映しています

上記で登録処理をするにあったって、Vue側で必要な実装は完了しましたので
残るは、TodoController.phpstore()アクションの実装を行えば登録ができるようになります

store()アクションの機能実装

それでは、VueからリクエストでPOSTされて送られてきたデータをLaravel側でDBに登録する処理を
store()に記述していきます
TodoController.phpを開きstore()に下記を追加してください

TodoController.php
public function store(Request $request)
{
    $request->user()->tasks()->create($request->all());

    return response('', 200);
}

$request->user()で現在の認証されているユーザーを所得しtasks()はリレーションで
Userのidとtodoのuser_idを紐づけています
tasks()->create($request->all())ここで新規追加を行っています
リレーションの設定はこのあと行います

User.phpを開いてリレーションを定義していきます

User.php
<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Todo;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function tasks() {    //追加
        return $this->hasMany(Todo::class);
    }
}

次にTodo::create($request->all())を実行するためにTodoモデルの作成と編集を行います
コマンドにて下記を実行してください
$ php artisan make:model Todo
上記を実行することで、appディレクトリ配下にTodo.phpが作成されます
これが、todosテーブルと紐づいたTodoのモデルになります
それでは、Todo.phpに下記を追加してください

Todo.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;    //追加

class Todo extends Model
{
    use SoftDeletes;    //追加

    protected $fillable = [    //追加
        'user_id','text'
    ];
}

ここではSoftDeletes(論理削除)を利用するための記述と
$fillabelを追加しました

論理削除はIlluminate\Database\Eloquent\SoftDeletesをuseで追加しモデル内でuse SoftDeletesとすることで利用できます

protected $fillabelここでuser_idtextを指定してます
todosテーブルのuser_idとtextを一括で更新をすることを許可しています
これを行うことで、先ほど記述したstore()内の処理で登録が行えます

これでtodo登録に必要な処理は一通り実装できました
一度フォームに入力して登録ボタンをクリックしてみてください
その後、DBのtodosテーブルに実際に登録できているかを確認してみてください
無事データがあれば完了です

確認方法が分からない方は、このまま一旦進んでください
次回のパートで表示機能を作りますので、そこで正常に登録が行えてるのかも確認できます

終わりに

今回は、todoの登録機能を実装しました
残る機能は、表示,更新,削除です
次回、表示機能の実装を行っていきます

次回のパートはこちら→Vue CLI × Laravel × VuetifyでCSSいらずの爆速開発でTodoリストを作る part7

6
4
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
4