【Laravel】Todoリストアプリの作成

#laravelでtodoアプリを作成

laravelでのCRUD処理理解のために、todoアプリを作成しました。その作成方法のメモです。

#完成版はコチラ

https://laravel-todo-jum.herokuapp.com/

#laravelプロジェクトの作成

```
$ cd laravelを管理するフォルダに移動
$ composer create-project --prefer-dist laravel/laravel="5.5"
```

#.envファイルの修正

```php:.env
DB_CONNECTION=sqlite
```

#データベースファイルの作成
```
$ cd database
$ touch database.sqlite
```


#テーブル設計

- モデル名は「Todo」とします
- テーブル名は「todos」になります。
- コントローラー名は「TodosController」とします。


#Todosテーブルのカラム構成
- id
- body：todoの内容
- created_at
- updated_at

※idとcreated_atとupdate_atは自動で作成されます。

#モデルとマイグレーションファイルの作成

```
$ cd .. （プロジェクトフォルダ直下に戻る）
$ php artisan make:model Todo --migration
Model created successfully.
Created Migration: 2019_12_14_015752_create_todos_table
```

#マイグレーションファイルの修正

```php:database/migrations/2019_12_14_015752_create_todos_table

    public function up()
    {
        Schema::create('todos', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->text('body'); //追加
            $table->timestamps();
        });
    }
```

#マイグレーションの実行

```
$ php artisan migrate
Migration table created successfully.
Migrating: 2019_12_14_015752_create_todos_table
Migrated:  2019_12_14_015752_create_todos_table (0.01 seconds)
```

#テーブルが作成されているか確認する
todosと表示されていれば、テーブルが作成されている。

```
$ sqlite3 database/database.sqlite
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> 

sqlite> .tables //テーブル一覧を取得
migrations  todos  

sqlite> PRAGMA table_info('todos'); //テーブル構造（カラム）を確認
0|id|integer|1||1
1|body|text|1||0
2|created_at|datetime|0||0
3|updated_at|datetime|0||0

sqlite> .q //sqliteを閉じる
$
```

#コントローラーの作成

```
$ php artisan make:controller TodosController
```

#ルーティングの設定



```php:routes/web.php

<?php

/*
|--------------------------------------------------------------------------
| 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('/', function () {
//    return view('welcome');
//});

Route::get('/','TodosController@index'); 
Route::resource('todos','TodosController');

```
resourcesでURIやコントローラーのメソッドは作成されるが、初期画面をindexにしたいので、Route::get・・・も追加する。

以下を参考にして表を作成
https://laraweb.net/knowledge/725/

| HTTPメソッド | URI | コントローラのメソッド | 用途 |
|:--|:--|:--|:--|
| GET | /todos | index() | 一覧表示 |
| GET | /todoss/create | create() | 追加ページ |
| POST | /todos | store() | 追加 |
| GET | /todos/{id} | show() | 該当データ表示 |
| GET | /todos/{id}/edit | edit() | 更新ページ |
| PUT | /todos/{id} | update() | 更新 |
| DELETE | /todos/{id} | destroy() | 削除 |

#Todosコントローラーの修正

```php:app/Http/Controllers/TodosController.php
<?php

namespace App\Http\Controllers;

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

class TodosController extends Controller
{
    //追加
        public function index() {
           $todos = Todo::all();
      return view('todos.index')->with('todos',$todos);
    }
    //追加
}
```

#todosテーブルに初期データを流し込む為のseederファイルを生成

```
$ php artisan make:seeder TodoTableSeeder
Seeder created successfully.
```

#作成したTodoTableSeederに流し込むデータ記載する

```php:database/seeds/TodoTableSeeder.php
<?php

use Illuminate\Database\Seeder;

class TodoTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
        $bodys = ['JCBギフト券を換金する','ゼルダの伝説をする','conohaのVPSで立ち上げをする'];
        foreach ($bodys as $body) {
          DB::table('todos')->insert([
            'body' => $body,
            'created_at' => new Datetime(),
            'updated_at' => new Datetime()
          ]);
        }
    }
}
```

#seederを実行（テーブルへの初期データ書き込み）するためにDatabaseSeederに記載する

```php:database/seeds/DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call(TodoTableSeeder::class);
    }
}
```

#seederを実行してtodosテーブルに書き込みする。

```
$ php artisan db:seed
Seeding: TodoTableSeeder
Database seeding completed successfully.
```

#todosテーブルに書き込まれているか確認する
```
$ sqlite3 database/database.sqlite
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from todos;
1|JCBギフト券を換金する||
2|ゼルダの伝説をする||
3|conohaのVPSで立ち上げをする||
```

#Viewの部分を作成していきます。
##index.balde.phpを作成する

```
$ cd resources/views
$ mkdir todos (todos関連のディレクトリを作成)
$ cd todos
$ vi index.blade.php (viewファイルの作成)
```

## bootstrap4を使います。
以下のリンクからコピーしましょう。
https://cccabinet.jpn.org/bootstrap4/getting-started/introduction
![スクリーンショット 2019-12-15 9.01.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420746/523ab791-ef76-5d70-0eac-5fd7b02d5e39.png)




```php:resources/views/todos/index.blade.php
<!doctype html>
<html lang="ja">
  <head>
    <title>Bootstrap基本テンプレート</title>
  <!-- 必要なメタタグ -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>
  <body>
    <h1>こんにちは!</h1>
    
  <!-- オプションのJavaScript -->
  <!-- 最初にjQuery、次にPopper.js、次にBootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
  </body>
</html>
```

##Todoリストの見た目の部分を作成します。

###変更内容は以下
- もろもろ
- todo作成フォーム
- todo追加ボタン
- todo編集ボタン
- todo削除ボタン

```php:rescources/views/todos/index.blade.php
<!doctype html>
<html lang="ja">
  <head>
    <title>Jum Todoリスト</title>
  <!-- 必要なメタタグ -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>
  <body>
    <div class="container" style="margin-top:50px;">
    <h1>Todoリスト追加</h1>

    <form action='{{ url('/todos')}}' method="post">
      {{csrf_field()}}
  <div class="form-group">
    <label >やることを追加してください</label>
    <input type="text" name="body"class="form-control" placeholder="todo list" style="max-width:1000px;">
  </div>
  <button type="submit" class="btn btn-primary">追加する</button>  </form>

    <h1 style="margin-top:50px;">Todoリスト</h1>
    <table class="table table-striped" style="max-width:1000px; margin-top:20px;">
    <!-- <thead>
    <tr>
      <th></th><th></th><th></th>
    </tr>
  </thead> -->
  <tbody>
    @foreach ($todos as $todo)
    <tr>
      <td>{{$todo->body}}</td>
      <td><form action="{{ action('TodosController@edit', $todo) }}" method="post">
          {{ csrf_field() }}
          {{ method_field('get') }}
          <button type="submit" class="btn btn-primary">編集</button>
      </form>
      </td>

      <!-- 削除ボタン -->
      <td><form action="{{url('/todos', $todo->id)}}" method="post">
          {{ csrf_field() }}
          {{ method_field('delete') }}
          <button type="submit" class="btn btn-danger">削除</button>
      </form>
      </td>

      <!-- 削除した際にポップ画面で確認をする -->
      <!-- <td><a class="del" data-id="{{ $todo->id }}" href="#">削除</a>
        <form method="post" action='{{ url('/todos', $todo->id) }}' id="form_{{ $todo->id}}">
          {{ csrf_field() }}
          {{ method_field('delete') }}
        </form>
      </td> -->
    </tr>
    @endforeach
  </table>
</div>
  <!-- オプションのJavaScript -->
  <!-- 最初にjQuery、次にPopper.js、次にBootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script>
    (function() {
  'use strict';

  var cmds = document.getElementsByClassName('del');
  var i;

  for (i = 0; i < cmds.length; i++) {
    cmds[i].addEventListener('click', function(e) {
      e.preventDefault();
      if (confirm('are you sure?')) {
        document.getElementById('form_' + this.dataset.id).submit();
      }
    });
  }

})();
</script>
  </body>
</html>
```

#コントローラーの修正

##todo追加処理

```php:app/Http/controllers/TodosController.php
    public function store(Request $request) {
      $todo = new Todo();
      $todo->body = $request->body;
      $todo->save();
      return redirect('/');
    }
```



##削除処理

```php:app/Http/controllers/TodosController.php
    public function destroy(todo $todo) {
        $todo->delete();
       return redirect('/');
     }
```

##編集処理

###編集する為のviewを作成

```
$ cd resources/views/todos
$ touch edit.blade.php
```

###edit.blade.phpを編集

```php:resources/views/todos/edit.blade.php
<!doctype html>
<html lang="ja">
  <head>
    <title>Jum Todoリスト</title>
  <!-- 必要なメタタグ -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  </head>

  <body>
    <div class="container" style="margin-top:50px;">
    <h1>Todoリスト更新</h1>

    <form action='{{ url('/todos',$todo->id) }}' method="post">
      {{csrf_field()}}
      {{ method_field('patch')}}
  <div class="form-group">
    <label >やることを更新してください</label>
    <input type="text" name="body"class="form-control" value="{{ $todo->body }}" style="max-width:1000px;">
  </div>
  <button type="submit" class="btn btn-primary">更新する</button>
</form>

</div>
  <!-- オプションのJavaScript -->
  <!-- 最初にjQuery、次にPopper.js、次にBootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <script>
    (function() {
  'use strict';

  var cmds = document.getElementsByClassName('del');
  var i;

  for (i = 0; i < cmds.length; i++) {
    cmds[i].addEventListener('click', function(e) {
      e.preventDefault();
      if (confirm('are you sure?')) {
        document.getElementById('form_' + this.dataset.id).submit();
      }
    });
  }

})();
</script>
  </body>
</html>
```

##編集画面への遷移処理（コントローラー）

```php:app/Http/controllers/TodosController.php
    public function edit(todo $todo) {
      return view('todos.edit')->with('todo',$todo);
    }
```

##更新処理(コントローラー)

```php:app/Http/controllers/TodosController.php
    public function update(Request $request,todo $todo) {
      $todo->body = $request->body;
      $todo->save();
      return redirect('/');
    }
```

#とりあえず完了

##ブラウザで確認

```
$ php artisan serve --host 192.168.33.10 --port 8000
Laravel development server started: <http://192.168.33.10:8000>
```
###初期画面(index)

![スクリーンショット 2019-12-15 10.52.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420746/f1c9a316-2c3a-0798-5b68-8bcaa29e4894.png)

###編集画面(edit)

![スクリーンショット 2019-12-15 10.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420746/f1a7bda7-6a8a-5308-eb06-68835c97f56c.png)

#その他の機能

##バリデーション

##フラッシュメッセージ


#終わりに

以上です。
これからlaravelを始める方は参考にしてみてください。