🔰

LaravelでTodoリストを実装してみよう!~実装編2:Todo追加機能の実装~

2024/06/19に公開

はじめに

今回は、Todo追加機能を実装していこうと思います!

前回の記事はこちら↓
https://zenn.dev/kenberu1200/articles/97df6d9fce1cbe

Todo追加画面の作成

まずは画面を実装していきます!

コンポーネントの作成:Todo追加ボタン

画面に配置するTodo追加ボタンを作成します。

sail artisan make:component element.button-addtodo --view

生成されたresources/views/components/element/button-addtodo.blade.phpファイルを以下のように書き換えます。

resources/views/components/element/button-addtodo.blade.php
<button
    type="submit"
    class="inline-flex justify-center py-2 px-4 border border-transparent
    shadow-sm text-sm font-medium rounded-md text-white bg-blue-500
    hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2
    focus:ring-blue-500"
>
    {{ $slot }}
</button>

ビューの作成

次にビューを作っていきます。ビューの生成には、以下のコマンドを実行します。

sail artisan make:view todolist.addtodo

生成されたresources/views/todolist/addtodo.blade.phpを以下のように書き換えます。

resources/views/todolist/addtodo.blade.php
<x-layout.layout title="Todo追加 | Todoアプリ">
    <x-layout.todolist-single>
        <form method="POST" action="{{ route('todolist') }}" class="justfy-center">
            <div class="flex flex-col justify-center">
                <div class="flex justify-center mb-4 text-4xl font-extralight text-green-500">Todo追加</div>
                @csrf

                <div class="flex justify-center items-center">
                    <div class="text-xl w-20">Todo</div>
                    <input type="text" name="content" placeholder="Todoを入力" class="@error('content') is-invalid @enderror w-96 ml-4 border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-green-500 dark:focus:border-green-600 focus:ring-green-500 dark:focus:ring-green-600 rounded-md shadow-sm">
                </div>
                @error('content')
                        <div style="color: red" class="alert alert-danger">{{ $message }}</div>
                @enderror
                <div class="flex justify-center items-center mt-4">
                    <div class="flex text-xl w-20">期限</div>
                    <input type="date" name="deadline" placeholder="YYYY-MM-DD" class="@error('deadline') is-invalid @enderror flex w-96 ml-4 border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-green-500 dark:focus:border-green-600 focus:ring-green-500 dark:focus:ring-green-600 rounded-md shadow-sm">
                </div>
                @error('deadline')
                        <div style="color: red" class="alert alert-danger">{{ $message }}</div>
                @enderror
                
                <div class="flex mt-4 justify-center">
                    <x-element.button-addtodo>追 加</x-element.button-addtodo>
                </div>
            </div>
        </form>
    </x-layout.todolist-single>
</x-layout.layout>

<form method="POST" action="{{ route('todolist') }}" class="justfy-center">の部分は便宜上既にあるtodolistにパスをつないでいますが、後程書き換えます。

コントローラーの作成

そして、コントローラーを作成します。

コントローラーファイルの生成には、以下のコマンドを実行します。

sail artisan make:controller Todolist/AddTodo/AddTodoPageController --invokable

生成されたapp/Http/Controllers/Todolist/AddTodo/AddTodoPageController.phpファイルを以下のように書き換えます。

app/Http/Controllers/Todolist/AddTodo/AddTodoPageController.php
<?php

namespace App\Http\Controllers\Todolist\AddTodo;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class AddTodoPageController extends Controller
{
    /**
     * Handle the incoming request.
     */
    public function __invoke(Request $request)
    {
+        return view('todolist.addtodo');
    }
}

ルーティング

最後に、ルーティングでパスをつないで完成です!

routes/web.phpに以下のコードを書き加えます。

routes/web.php
//// 省略 ////
Route::get('addtodo-page',\App\Http\Controllers\Todolist\AddTodo\AddTodoPageController::class)
    ->name('addtodo-page');

http://localhost/addtodo-pageにアクセスすると以下のような画面が表示されていれば完成です!

まだTodo追加機能を実装していないので、追加ボタンを押してもエラーが出ます。

Todo追加機能の作成

続いて、追加ボタンを押したときに実際にTodoが追加されるように機能を実装していきましょう!

リクエストの作成

まず、追加ボタンを押したときに、入力した情報をコントローラーに送信できるようにリクエストを作っていきます。

リクエストファイルを生成するには以下のコマンドを実行します。

sail artisan make:request Todolist/AddTodoRquest

生成されたapp/Http/Requests/Todolist/AddTodoRquest.phpファイルを以下のように書き換えます。

app/Http/Requests/Todolist/AddTodoRquest.php
<?php

namespace App\Http\Requests\Todolist;

use Illuminate\Foundation\Http\FormRequest;

class AddTodoRquest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
-        return false;
+        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
+           'content'  => 'required',
+           'deadline' => 'required|date',
        ];
    }
+    public function userId() : int {
+        return $this->user()->id;
+    }

+    public function content(): string {
+        return $this->input('content');
+    }

+    public function deadline(): string {
+        return $this->input('deadline');
+    }
}

コントローラーの作成

次に、コントローラーを作成していきます。

sail artisan make:controller Todolist/AddTodo/AddTodoController --invokable

生成されたapp/Http/Controllers/Todolist/AddTodo/AddTodoController.phpを以下のように書き換えます。

app/Http/Controllers/Todolist/AddTodo/AddTodoController.php
<?php

namespace App\Http\Controllers\Todolist\AddTodo;

use App\Http\Controllers\Controller;
+use App\Models\Todolist;
+use App\Http\Requests\Todolist\AddTodoRquest;
-use Illuminate\Http\Request;

class AddTodoController extends Controller
{
    /**
     * Handle the incoming request.
     */
-    public function __invoke(Request $request)
+    public function __invoke(AddTodoRquest $request)
    {
+        $todo = new Todolist();
+        $todo->user_id = $request->userId();
+        $todo->content = $request->content();
+        $todo->deadline = $request->deadline();
+        $todo->save();
+        return redirect()->route('todolist');
    }
}

ルーティング

routes/web.phpに以下のコードを書き加えます。

routes/web.php
//// 省略 ////
Route::post('todo/addtodo',\App\Http\Controllers\Todolist\AddTodo\AddTodoController::class)
    ->name('addtodo');

ビューの修正

そして、ビューファイルの便宜上todolistにパスをつないでいた

<form method="POST" action="{{ route('todolist') }}" class="justfy-center">の部分を書き換えます。

resources/views/todolist/addtodo.blade.php
<x-layout.layout title="Todo追加 | Todoアプリ">
    <x-layout.todolist-single>
-        <form method="POST" action="{{ route('todolist') }}" class="justfy-center">
+        <form method="POST" action="{{ route('addtodo') }}" class="justfy-center">
{{-- 省略 --}}

現状、ユーザーログイン機能を実装していないので、以下のようなエラー画面が出ます。

とりあえず追加機能を試したい人へ

現状ユーザーログインがないので、マイグレーションファイルのユーザーIDを記録するカラムにデフォルト値を設定しましょう。

database/migrations/2024_04_24_004237_create_todolists_table.php
public function up(): void
    {
        Schema::create('todolists', function (Blueprint $table) {
            $table->id();
-            $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
+            $table->foreignId('user_id')->default(1)->constrained('users')->cascadeOnDelete();
            $table->string('content');
            $table->date('deadline');
            $table->boolean('status')->default(0);
            $table->timestamps();
        });
    }

マイグレーションファイルを編集したので、マイグレーションをリフレッシュして再度シーディングもしておきましょう。

sail artisan migrate:refresh --seed
sail artisan db:seed --class=TodoSeeder

後は、リクエストとコントローラーのuserIdにかかわる部分をコメントアウトしておけば機能するようになります。

app/Http/Controllers/Todolist/AddTodo/AddTodoController.php
public function __invoke(AddTodoRquest $request)
    {
        $todo = new Todolist();
        // $todo->user_id = $request->userId(); //コメントアウト
        $todo->content = $request->content();
        $todo->deadline = $request->deadline();
        $todo->save();
        return redirect()->route('todolist');
    }
app/Http/Requests/Todolist/AddTodoRquest.php
    // public function userId() : int {
    //     return $this->user()->id;
    // }

ファイルを保存したら、Todo追加画面を再読み込みして、追加ボタンを押すとTodoが追加されているはずです。

おわりに

今回は、Todo追加画面と機能をコーディングしました。

ユーザー認証の機能を実装していないので、このままでは動きませんが、次々回くらいの記事でログイン機能追加しようと思います!

ではまた!

Discussion