ユーザー登録画面を作成しながらDBを操作する画面作成の基礎を勉強してみる～削除機能の実装～

削除機能を実装します。
こんなイメージです。

**削除ボタンを押す**
↓
削除していいか確認ダイアログが表示される→**いいえを選択する**→何もしない
↓
**はいを選択する**
↓
*ユーザが削除される*
↓
*ユーザー一覧が再表示される*


## 手順

 1. 削除確認ダイアログを作成します
 2. 削除処理を実装します

### 1. 削除確認ダイアログを実装します

jQueryを使用して、削除確認ダイアログを実装します。
jQueryについては割愛します。

```html:resources/view/users/index.blade.php
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="row p-1">
        <div class="col">
          <a class="btn btn-secondary" href="/users/create">新規作成</a>
        </div>
      </div>
      <div class="row p-1">
        <div class="col">
          <table class="table">
          <tr><th>ID</th><th>氏名</th><th>メールアドレス</th><th></th><th></th><th></th></tr>
          @foreach($users as $user)
          <tr>
            <td>{{ $user->id }}</td>
            <td>{{ $user->name }}</td>
            <td>{{ $user->email }}</td>
            <td><a class="btn btn-secondary" href="/users/{{ $user->id }}">参照</a></td>
            <td><a class="btn btn-secondary" href="/users/{{ $user->id }}/edit">編集</a></td>
            <td>
              <form method="post" action="/users/{{ $user->id }}">
                {{ csrf_field() }}
                {{ method_field('DELETE') }}
                <input class="btn btn-secondary" type="submit" value="削除" data-btn-dell>
              </form>
            </td>
          </tr>
          @endforeach
          </table>
        </div>
      </div>
    </div>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script>
    $(function() {
      $('[data-btn-dell]').on('click', function() {
        return confirm('削除してよろしいですか？');
      });
    });
  </script>
  </body>
</html>
```

### 2. 削除処理を実装します

コントローラに削除処理を実装します。
`User::find($id)`で取得したモデルインスタンスの`delete()`を呼び出して削除することができます。
該当するレコードが存在しない場合に例外を投げたい場合は、`User::find($id)`の代わりに`User::findOrFail($id)`を呼び出します。投げられる例外は`ModelNotFoundException`で例外がキャッチされない場合は404が返されます。

```php:app/Http/Controllers/UserController.php
    // 削除処理
    public function destroy(Request $request, $id)
    {
      // 削除対象のインスタンスを取得します
      $user = User::find($id);
      // 削除します
      $user->delete();
      // ユーザー一覧画面にリダイレクトします
      return redirect('/users');
    }
```

## ソフトデリートについて

これまでに紹介した削除処理は物理削除（レコード自体を削除する）ですが、ソフトデリート（論理削除）もあります。ソフトデリートの場合、`deleted_at`カラムに削除日時が設定されます。

ソフトデリートを使用するための準備は次の通りです。

 - データベーステーブルにソフトデリートカラムを設定する

```php:ほにゃらら_create_users_table.php
<?php

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

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
            // ソフトデリートを有効にする
            $table->softDeletes();
        });
    }

    public function down()
    {
        Schema::dropIfExists('users');
    }
}
```

 - モデルのソフトデリートを有効にする

```php:
<?php

namespace App;

use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;
    // ソフトデリートの設定
    use SoftDeletes;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];
    // ソフトデリートの設定
    protected $dates = ['deleted_at'];
}
```

モデルに対する操作は次の通りです。

```php
  $user = User::findOrFail(1);
  // レコードを削除する
  $user->delete();
  // ソフトデリートの解除
  $user->restore();
  // モデルの完全削除
  $user->forceDelete();
```

ソフトデリートしたレコードは`User::all()`ではヒットしません。次のように取得できます。

```php
  // ソフトデリート済みモデルも含めて取得する
  $users = User::withTrashed()
               ->get();
  // ソフトデリート済みモデルのみ取得する
  $users = User::onlyTrashed()
               ->get();
```

## 参考

[Laravel Document](https://readouble.com/laravel/5.5/ja/eloquent.html)