LaravelでToDoアプリを開発する Part2

Laravel

はじめに

本記事は「LaravelでToDoアプリを開発する Part1」の続きになります。

Part1をまだ見ていない方はぜひそちらからご覧ください。

タスクテーブル作成

まずはToDoを保存するテーブルが必要になりますので、タスクテーブルを作成します。

以下のコマンドでタスクテーブルのマイグレーションファイルを作成します。

$ php artisan make:migration create_tasks_table --create=tasks

次に、タスクテーブルのマイグレーションファイルを以下のように編集します。

database/migrations/YYYY_*mm_*dd_XXXXXXXX_create_tasks_table.php

<?php

use Illuminate\\Database\\Migrations\\Migration;
use Illuminate\\Database\\Schema\\Blueprint;
use Illuminate\\Support\\Facades\\Schema;

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('title')->comment('タイトル');
            $table->text('body')->comment('本文');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tasks');
    }
}

タイトルと本文のカラムを追加しています。

そして、以下のコマンドでDBに反映させます。

$ php artisan migrate

成功したら、phpMyAdminでデータベースに入ってtasksテーブルができているか確認してみてください。

tasksテーブルが作成されていたら成功です。

Gitにコミットしておきましょう。

$ git status
$ git diff ファイル名
$ git add ファイル名

最初に解説した通りに変更ファイルを1ファイルずつ確認して行ってください。

すべて問題がなければコミットします。

$ git commit -m "タスクテーブル作成"

タスクモデル作成

次に、今回作成するアプリはToDoアプリなので、LaravelでToDoを管理するモデルが必要になります。

そこで、以下のコマンドでタスクモデルを作成しておきましょう。

php artisan make:model Task

これでapp/Models/Task.phpが作成されたはずです。

そしてタスクモデルに以下の一文を追加しておきましょう。

protected $fillable = ['title', 'body'];

これはホワイトリストと言って、create()やfill()やupdate()メソッドを使用する際にここで指定されたカラムしか変更できませんという意味合いになります。

要するに、ここで指定したカラム以外のカラムは新規作成や更新ができなくなるということです。

これで、タスクモデルは以下のようになるはずです。

app/Models/Task.php

<?php

namespace App\\Models;

use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;

class Task extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'body'];
}

Gitにコミットしておきましょう。

$ git status
$ git diff ファイル名
$ git add ファイル名

最初に解説した通りに変更ファイルを1ファイルずつ確認して行ってください。

すべて問題がなければコミットします。

$ git commit -m "タスクモデル作成"

タスク新規登録機能作成

ToDoを作成できなければ始まらないので、まずはToDoを画面から作成する機能を作っていきましょう。

ルーティング作成

機能を作成する前に、新規作成用のルーティングを一本追加しておきます。

app/routes/web.php

<?php

use Illuminate\\Support\\Facades\\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', [App\\Http\\Controllers\\HomeController::class, 'index'])->name('task.index');
Route::post('/create', [App\\Http\\Controllers\\HomeController::class, 'store'])->name('task.create');   // 追加

新規作成の場合はHTTPメソッドを「post」としておきます。

Controller作成

HomeControllerにstoreアクションを追加し、その中にクライアントから送られてきたデータをDBに保存する処理を書いていきます。

HomeControllerを開いて、以下のように記述します。

app/Http/Controllers/HomeController

public function store(Request $request) {
        $task = new Task();
        $task->title = $request->title;
        $task->body = $request->body;
        $task->save();

        return redirect()->route('task.index');
}

保存処理はさまざまな書き方がありますが、以下の一文でまずTaskモデルのインスタンスを作成しています。

$task = new Task();

そして、以下で作成したインスタンスにプロパティを設定していきます。

$task->title = $request->title;
$task->body = $request->body;

作成したプロパティの値はクライアントからリクエストで送られてきた値を代入しています。

最後に、インスタンスをsave()することでtasksテーブルに保存しています。

 $task->save();

保存処理はさまざまな書き方がありますが、実務ではこのsave()メソッドが使われていることが多い印象があります。

少し突っ込んだ解説をすると、このsave()メソッドには面白い特徴があります。

save()メソッドは保存する際にDBに既に同じデータが存在するかどうかをまずチェックしています。今から入れようとしているデータと全く同じものがDBに既に存在する場合は更新を行いません。また、新しいデータを入れようとしている場合はデータをDBに新規作成します。

つまり、今から入れようとしているデータとDBのデータの差分を見て、更新や新規作成を行っているのです。

更新に限定すると、似たようなメソッドにupdate()がありますが、これはDBのデータを見ずに関係なく更新します。これがupdate()とsave()メソッドの違いです。なので、save()メソッドを使うと新規作成だろうと更新だろうと使えてしまうわけです。

後はhomeのViewにリダイレクトするだけです。

return redirect()->route('task.index');

次に、既に作成しているindexアクションを修正していきます。

現状だと動作確認の際に作成したユーザー情報を取得するようになっているかと思いますので、これをタスクに修正します。

app/Http/Controllers/HomeController.php

public function index() {
    $tasks = Task::all();
    return view('home', ['tasks' => $tasks]);
}

これはユーザー→タスクに置き換えているだけです。

これでタスク情報を取得しています。

最後にViewを作成します。

View作成

一画面で新規作成用のフォームとタスク一覧表示を作ります。

resources/views/home.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>TODOアプリ</title>
</head>
<body>
    <div class="container" style="width: 80%; display: flex; flex-direction: column; justify-content: center; margin: 0 auto;">
        <div style="display: flex; justify-content: center;">
            <form action="{{ route('task.create') }}" method="POST" style="display: flex; flex-direction: column; justify-content: center; width: 20%; gap: 30px;">
                @csrf
                <div style="display: flex; flex-direction: column;">
                    <label for="">タイトル</label>
                    <input type="text" name="title" />
                </div>
                <div style="display: flex; flex-direction: column;">
                    <label for="">説明</label>
                    <textarea name="body" id="body" cols="30" rows="10"></textarea>
                </div>
                <button type="submit">作成</button>
            </form>
        </div>
        <div style="display: flex; justify-content: center; margin-top: 100px;">
            <table>
                <thead>
                    <tr>
                        <th>タイトル</th>
                        <th>作成日</th>
                        <th>更新日</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($tasks as $task)
                    <tr>
                        <td>{{ $task->title }}</td>
                        <td>{{ $task->created_at }}</td>
                        <td>{{ $task->updated_at }}</td>
                    </tr>
                    @endforeach
                </tbody>
            </table>
        </div>
    </div>
</body>
</html>

まずはフォームの部分から見ていきます。

<form action="{{ route('task.create') }}" method="POST" style="display: flex; flex-direction: column; justify-content: center; width: 20%; gap: 30px;">
    @csrf
     <div style="display: flex; flex-direction: column;">
         <label for="">タイトル</label>
         <input type="text" name="title" />
     </div>
     <div style="display: flex; flex-direction: column;">
          <label for="">説明</label>
          <textarea name="body" id="body" cols="30" rows="10"></textarea>
     </div>
     <button type="submit">作成</button>
</form>

フォームの書き方もさまざまありますが、基本的にはformタグのactionにルート名を記述すれば指定したルーティングに飛ばせるようになります。

今回は新規作成なので、methodは「POST」となります。

また、Laravelの場合はフォームを作成する場合は@csrfを記述する必要があります

これは今はまだ詳しく知らなくても良いですが、セキュリティ上必要な記述とだけ覚えておいてください。

次に表示部分です。

<div style="display: flex; justify-content: center; margin-top: 100px;">
    <table>
        <thead>
            <tr>
                <th>タイトル</th>
                <th>作成日</th>
                <th>更新日</th>
            </tr>
         </thead>
         <tbody>
             @foreach ($tasks as $task)
              <tr>
                  <td>{{ $task->title }}</td>
                  <td>{{ $task->created_at }}</td>
                  <td>{{ $task->updated_at }}</td>
              </tr>
             @endforeach
         </tbody>
     </table>
</div>

bladeテンプレートでは繰り返し処理を書く場合に以下のように記述します。

@foreach ($tasks as $task)
  ・・・
 @endforeach

ここでは、Controllerで渡した$tasksというタスク情報の入った配列を繰り返し処理で順に表示しています。

ここまでで以下のような画面ができていれば成功です。

https://images.microcms-assets.io/assets/3657adca675f4cff92c75e357693d803/c8c53513eceb416db04facdb99d9f0f7/スクリーンショット 2023-01-08 17.21.54.png

実際にフォームからタスクを作成してみて、表に追加されるか確認してみましょう。

これでタスク作成機能とタスク一覧表示機能を作成することができました!

次の実装に入る前にある程度Viewの全体像が見えてきたので、ここでCSSを使ってサイトデザインを少し整えていきましょう。

また、Gitにコミットしておきます。

$ git status
$ git diff ファイル名
$ git add ファイル名

最初に解説した通りに変更ファイルを1ファイルずつ確認して行ってください。

すべて問題がなければコミットします。

$ git commit -m "タスク新規登録作成"

デザイン調整

HTML/CSSに関しては本記事での解説は割愛させていただきます。

また、別記事にてHTML/CSSの詳細を解説している記事がありますので、ご確認いただければと思います。

以下にコードを載せておきます。

resources/views/home.blade.php

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>TODOアプリ</title>
</head>
<body>
    <div class="container">
        <div class="form-wrapper">
            <form action="{{ route('task.create') }}" method="POST">
                @csrf
                <div class="form-group">
                    <label for="">タイトル</label>
                    <input type="text" name="title" />
                </div>
                <div class="form-group">
                    <label for="">説明</label>
                    <textarea name="body" id="body" cols="30" rows="10"></textarea>
                </div>
                <button type="submit" class="submit">作成</button>
            </form>
        </div>
        <div class="table-wrapper">
            <table>
                <thead>
                    <tr>
                        <th>タイトル</th>
                        <th>作成日</th>
                        <th>更新日</th>
                        <th>編集</th>
                        <th>削除</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($tasks as $task)
                    <tr>
                        <td>{{ $task->title }}</td>
                        <td>{{ $task->created_at }}</td>
                        <td>{{ $task->updated_at }}</td>
                        <td>
                            <a href="/edit" class="edit">編集</a>
                        </td>
                        <td>
                            <a href="/delete" class="delete">削除</a>
                        </td>
                    </tr>
                    @endforeach
                </tbody>
            </table>
        </div>
    </div>
    <style>
        .container {
            width: 80%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            margin: 0 auto;
        }
        .container .form-wrapper {
            display: flex;
            width: 650px;
            justify-content: left;
            margin: 0 auto;
            margin-top: 50px;
        }
        .container .form-wrapper form {
            display: flex;
            flex-direction: column;
            gap: 30px;
            width: 60%;
        }
        .container .form-wrapper form button {
            border: 1px solid black;
            border-radius: 15px;
            background-color: skyblue;
            width: 100px;
            cursor: pointer;
        }
        .container .form-wrapper form .form-group {
            display: flex;
            flex-direction: column;
        }
        .container .table-wrapper {
            display: flex;
            justify-content: center;
            margin-top: 100px;
        }
        .container .table-wrapper table {
            border-collapse: collapse;
        }
        .container .table-wrapper table th,td {
            border: solid 1px;
            padding: 10px;
        }
        .edit {
            border: 1px solid black;
            padding: 5px 10px;
            border-radius: 10%;
            color: black;
            background-color: skyblue;
            text-decoration: none;
        }
        .delete {
            border: 1px solid black;
            padding: 5px 10px;
            border-radius: 10%;
            color: black;
            background-color: red;
            text-decoration: none;
        }
    </style>
</body>
</html>

サイトの見た目は以下のようになるはずです。

https://images.microcms-assets.io/assets/3657adca675f4cff92c75e357693d803/d3dad3b602de4bb584e502381135f083/スクリーンショット 2023-01-08 20.40.46.png

Gitにコミットしておきましょう。

$ git status
$ git diff ファイル名
$ git add ファイル名

最初に解説した通りに変更ファイルを1ファイルずつ確認して行ってください。

すべて問題がなければコミットします。

$ git commit -m "サイトが殺風景なので、デザイン調整"

次は、タスク詳細画面とタスク更新機能について解説します。

コメント

タイトルとURLをコピーしました