Laravel 10days チャレンジ! 10日目 〜TODOアプリを作ろう 実装編〜

Laravel

みなさんこんにちは、ちょいまけです。

今回は「Laravelをゼロから10日でどこまで習得できるのか」という企画の10日目です。

この企画が始まった経緯が知りたい方はコチラをご確認ください。

この記事では、LaravelでのTODOアプリの実装と結果報告を行います。よろしければ、お付き合いください。

TODOアプリ完成

実装の紹介の前に、実際のアプリの動作を見ていただきたいと思います。設計編と画面デザインがちょっと違いますが、そこはスルーでお願いします。

TODOアプリ実装

上記の動画の通り、無事TODOアプリを作ることができました。それでは具体的にどう実装したのかをこれから紹介します。

マイグレーションとシーディング

まずマイグレーションとシーディングの設定についてです。

Tasksテーブルの定義

設計編で作ったテーブル定義をコードに落とし込みます。検索用にインデックスの追加も行っています。

<?php

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

class CreateTasksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {

            // columns
            $table->bigIncrements('id');
            $table->string('title', 100);
            $table->string('detail', 100);
            $table->integer('status');
            $table->timestamps();

            // index
            $table->index('status');
        });
    }

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

Tasksのシーディング

tasksテーブルの初期値を作ります。データの内容は適当で大丈夫です。

<?php

use Illuminate\Database\Seeder;

class TasksTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // 初期値として入れるデータの定義をinsert処理
        $param = [
            'title' => 'ランニング',
            'detail' => 'ダイエットのために5キロほど走る',
            'status'  => 1,
            'created_at' => '2018-12-12 00:10:00',
            'updated_at' => '2018-12-12 00:10:00'
        ];
        DB::table('tasks')->insert($param);
        $param = [
            'title' => '友達と会う',
            'detail' => '久しぶりに友達とテニスをする',
            'status'  => 1,
            'created_at' => '2018-12-21 00:10:00',
            'updated_at' => '2018-12-23 00:10:00'
        ];
        DB::table('tasks')->insert($param);

        $param = [
            'title' => 'TVを見る',
            'detail' => '最近お笑いにハマってるよ',
            'status'  => 2,
            'created_at' => '2018-12-12 00:15:00',
            'updated_at' => '2018-12-14 13:10:00'
        ];
        DB::table('tasks')->insert($param);
        $param = [
            'title' => '歯を磨く',
            'detail' => 'うっかり忘れないように',
            'status'  => 2,
            'created_at' => '2018-12-12 00:15:00',
            'updated_at' => '2018-12-15 13:10:00'
        ];
        DB::table('tasks')->insert($param);
    }
}

タスク一覧

tasksモデルを作った後、TODOアプリのコントローラのTaskControllerを作成し、一覧用の処理を追加します。

class TaskController extends Controller
{
    /**
     * task 一覧表示
     */
    public function index()
    {
        // 未完了タスクのデータを取得
        $incomp_tasks = Task::where('status', Task::STATUS_INCOMPLETE)->get();
        // 完了タスクのデータを取得
        $comp_tasks = Task::where('status', Task::STATUS_COMPLETE)->get();

        $view_data = [
            'incomp_tasks' => $incomp_tasks,
            'comp_tasks' => $comp_tasks,
        ];

        return view('task.index', $view_data);
    }
.
.
.

テンプレート部分を作成します。まずは基礎となるbase.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>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <style>
    @yield('css')
  </style>
</head>
<body>
  <main>
    @yield('content')
  </main>
</body>
</html>

タスク一覧表示用のindex.blade.phpを作ります。

@extends('layouts.base')

@section('css')
* {
  color: #707070;
}
.content {
  margin-top: 40px;
  width: 90%;
  margin-left: auto;
  margin-right: auto;
  display:flex;
  flex-direction: row;
}
.todo-list-content {
  position: relative;
  width: 70%;
  margin: 0 auto;
}
.task-area {
  position: absolute;
  width: 100%;
}
.task-board {
  border: solid 1px #707070;
  margin-bottom: 5px;
  display:flex;
}
.task-title {
  margin: 0 auto;
}
.task-detail {
  margin: 0 auto;
}
.task-board-left {
  width: 90%
}
.task-board-right {
  display:flex;
  flex-direction: column;
}
.comp-task-bg {
  background-color: #e3e3e3;
}
@endsection

@section('content')

<div class="content">
  <div class="todo-list-content">
    <div>TODOリスト</div>
    <div class="task-area">
      <div class="incompleted-task-list">
        @foreach ($incomp_tasks as $task)
          <div class="task-board">
            <div class="task-board-left">
              <div class="task-title">
                {{$task->title}}
              </div>
              <div class="task-detail">
                {{$task->detail}}
              </div>
            </div>
            <div class="task-board-right">
              <a href="/task/edit?id={{$task->id}}" class="btn btn-info" role="button">更新</a>
              <a href="/task/del?id={{$task->id}}" class="btn btn-danger" role="button">削除</a>
            </div>
          </div>
        @endforeach
      </div>
      <div>完了済み</div>
      <div class="completed-task-list">
          @foreach ($comp_tasks as $task)
            <div class="task-board comp-task-bg">
              <div class="task-board-left">
                <div class="task-title">
                  {{$task->title}}
                </div>
                <div class="task-detail">
                  {{$task->detail}}
                </div>
              </div>
              <div class="task-board-right">
                <a href="/task/edit?id={{$task->id}}" class="btn btn-info" role="button">更新</a>
                <a href="/task/del?id={{$task->id}}" class="btn btn-danger" role="button">削除</a>
              </div>
            </div>
          @endforeach
        </div>
    </div>
  </div>
  <a href="/task/add" class="btn btn-primary" role="button">追加</a>
</div>
@endsection

タスク追加

TaskControllerにタスク追加処理を追加します。

/**
 * task 追加入力
 */
public function add()
{
    return view('task.add');
}

/**
 * task 追加実行
 */
public function create(Request $request)
{
    $task = new Task();
    $task->title = $request->title;
    $task->detail = $request->detail;
    $task->status = Task::STATUS_INCOMPLETE;
    $task->save();

    return redirect('/task');
}

タスク一覧追加用のadd.blade.phpを作ります。

@extends('layouts.base')

@section('css')
.content {
  margin-top: 40px;
  width: 90%;
  margin-left: auto;
  margin-right: auto;
}

@endsection

@section('content')
<div class="content">
  <form action="/task/add" method="post">
    @csrf
    <div style="font-size:24px;margin-bottom:20px;">タスクを追加します</div>
    <div>タスク名</div>
    <input type="text" name="title" required>
    <div>詳細</div>
    <input type="text" name="detail" size=80>
    <input type="submit" value="追加" class="btn btn-primary">
    <a href="/task" class="btn btn-danger">キャンセル</a>
  </form>
</div>
@endsection

タスク編集

TaskControllerにタスク編集処理を追加します。

/**
* task 編集入力
*/
public function edit(Request $request)
{
    $task = Task::where('id', $request->id)->first();

    return view('task.edit', ['task' => $task]);
}

/**
* task 更新処理
*/
public function update(Request $request)
{
    $task = Task::where('id', $request->id)->first();
    $task->title = $request->title;
    $task->detail = $request->detail;
    $task->status = $request->status;
    $task->save();

    return redirect('/task');
}

タスク一覧更新用のedit.blade.phpを作ります。

@extends('layouts.base')

@section('css')
.content {
  margin-top: 40px;
  width: 90%;
  margin-left: auto;
  margin-right: auto;
}

@endsection

@section('content')
<div class="content">
  <form action="/task/edit" method="post">
    @csrf
    <div style="font-size:24px;margin-bottom:20px;">タスクを更新します</div>
    <div>タスク名</div>
    <input type="hidden" name="id" value={{$task->id}}>
    <input type="text" name="title" required value={{$task->title}}>
    <div>詳細</div>
    <input type="text" name="detail" size=80 value={{$task->detail}}>
    <div>状態</div>
    <label><input type="radio" name="status" value="1" @if ($task->status === 1)checked @endif>未完了</label>
    <label><input type="radio" name="status" value="2" @if ($task->status === 2)checked @endif>完了</label>
    <input type="submit" value="更新" class="btn btn-primary">
    <a href="/task" class="btn btn-danger">キャンセル</a>
  </form>
</div>
@endsection

タスク削除

TaskControllerにタスク削除処理を追加します。

/**
* task 削除確認
*/
public function del(Request $request)
{
    $task = Task::where('id', $request->id)->first();

    return view('task.del', ['task' => $task]);
}

/**
* task 削除実行
*/
public function remove(Request $request)
{
    $task = Task::where('id', $request->id)->delete();

    return redirect('/task');
}

タスク一覧削除用のdel.blade.phpを作ります。

@extends('layouts.base')

@section('css')
.content {
  margin-top: 40px;
  width: 90%;
  margin-left: auto;
  margin-right: auto;
}

@endsection

@section('content')
<div class="content">
  <form action="/task/del" method="post">
    @csrf
    <div style="font-size:24px;margin-bottom:20px;">タスクを更新します</div>
    <div>タスク名</div>
    <input type="hidden" name="id" value={{$task->id}}>
    <input type="text" name="title" readonly value={{$task->title}}>
    <div>詳細</div>
    <input type="text" name="detail" size=80 readonly value={{$task->detail}}>
    <div>状態</div>
    @if ($task->status === 1)
      <div class="status">完了</div>
    @else
    <div class="status">未完了</div>
    @endif
    <input type="submit" value="削除" class="btn btn-danger">
    <a href="/task" class="btn btn-light">キャンセル</a>
  </form>
</div>
@endsection

ルーティング

web.phpでルーティング設定をします。これでアプリの実装はおしまいです。

Route::get('task', 'TaskController@index');

Route::get('task/add', 'TaskController@add');
Route::post('task/add', 'TaskController@create');

Route::get('task/edit', 'TaskController@edit');
Route::post('task/edit', 'TaskController@update');

Route::get('task/del', 'TaskController@del');
Route::post('task/del', 'TaskController@remove');

さいごに

「Laravel 10days チャレンジ! 10日目 〜TODOアプリを作ろう 実装編〜」いかがだったでしょうか?今回はLaravelでのTODOアプリの実装を行いました。

「Laravelを10日でどこまで習得できるか」ということにチャレンジした結果ですが、最終的に簡単なTODOアプリを作るところまではできるようになりました。

正直現場レベルまでLaravelを習得できたかといわれたらまだまだ全然足りませんが、勉強の内容をブログでアウトプットするという自分で初の試みにチャレンジしたことで、様々な経験や気付きを得ることができました。

これで一旦Laravelの勉強は一区切りとさせていただきますが、これからまた色んなことを勉強して、それらの中で得た知見をブログでアウトプットしたいと考えています。

今回の企画はこれで以上です。
最後まで読んでいただきまして、ありがとうございました。

コメント

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