Laravel5.7: postsのCRUD機能を実装する

postsテーブルに関するCRUD機能を実装します。
usersテーブルと重複する説明は簡略化します。
:link: [usersのCRUD機能を実装する](https://qiita.com/sutara79/items/cd4371b246b44a2cf87f)


# 親記事
[Laravel 5.7で基本的なCRUDを作る - Qiita](https://qiita.com/sutara79/items/ef30fcdfb7afcb2188ea)


# postsのモデル、コントローラを作る
```text:PowerShell
# モデル生成
> php artisan make:model Post

# コントローラ生成
> php artisan make:controller PostController --resource
```

```php:routes/web.php
// ルート追加
Route::resource('posts', 'PostController');
```

```diff:app/Http/Controllers/PostController.php
 use Illuminate\Http\Request;
+use App\Post; // Postモデルをインポートする

 class PostController extends Controller
 {
```


# 一覧表示 (index)
![001.png](https://qiita-image-store.s3.amazonaws.com/0/27816/b5d8286b-0a0f-a882-0c7c-2be4182de3d6.png)

## コントローラ
投稿日の新しい順で記事を一覧表示します。
`orderBy`メソッドよりも`latest`メソッドが便利です。

```php:app/Http/Controllers/PostController.php
    public function index()
    {
        // 1. 新しい順に取得できない
        // $posts = Post::all();

        // 2. 記述が長くなる
        // $posts = Post::orderByDesc('created_at')->get();

        // 3. latestメソッドがおすすめ
        $posts = Post::latest()->get();

        return view('posts.index', ['posts' => $posts]);
    }
```

`orderBy`, `latest`はクエリビルダのメソッドですが、下記の通りEloquentモデルでも使えます。

> Eloquentモデルはクエリビルダですから、クエリビルダで使用できる全メソッドを確認しておくべきでしょう。Eloquentクエリでどんなメソッドも使用できます。

:link: readouble.com: [Eloquent：利用の開始](https://readouble.com/laravel/5.7/ja/eloquent.html#retrieving-models)

クエリビルダの解説は下記を。
:link: readouble.com: [クエリビルダ](https://readouble.com/laravel/5.7/ja/queries.html)
:link: Laravel API: [クエリビルダのクラス](https://laravel.com/api/5.7/Illuminate/Database/Query/Builder.html)

なお、`all`は`Model`クラスのメソッドです。
:link: Laravel API: [Model::all](https://laravel.com/api/5.7/Illuminate/Database/Eloquent/Model.html#method_all)

## ビュー
usersと同じく、レイアウトとBootstrapを利用します。

```html:resources/views/posts/index.blade.php
@php
    $title = __('Posts');
@endphp
@extends('layouts.my')
@section('content')
<div class="container">
    <h1>{{ $title }}</h1>
    <div class="table-responsive">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>{{ __('Title') }}</th>
                    <th>{{ __('Body') }}</th>
                    <th>{{ __('Created') }}</th>
                    <th>{{ __('Updated') }}</th>
                </tr>
            </thead>
            <tbody>
            @foreach ($posts as $post)
                <tr>
                    <td>
                        <a href="{{ url('posts/'.$post->id) }}">{{ $post->title }}</a>
                    </td>
                    <td>{{ $post->body }}</td>
                    <td>{{ $post->created_at }}</td>
                    <td>{{ $post->updated_at }}</td>
                 </tr>
            @endforeach
            </tbody>
        </table>
    </div>
</div>
@endsection
```

# 1件表示 (show)
![002.png](https://qiita-image-store.s3.amazonaws.com/0/27816/ccf09b9b-a8d6-7742-8477-f0186594deae.png)

## コントローラ
```php:app/Http/Controllers/PostController.php
    /**
     * Display the specified resource.
     *
     * @param  \App\Post $post
     * @return \Illuminate\Http\Response
     */
    public function show(Post $post)
    {
        return view('posts.show', ['post' => $post]);
    }
```

## ビュー
usersと同じく、削除ボタン用のコンポーネントを利用します。

```html:resources/views/posts/show.blade.php
@php
    $title = $post->title;
@endphp
@extends('layouts.my')
@section('content')
<div class="container">
    <h1 id="post-title">{{ $title }}</h1>

    {{-- 編集・削除ボタン --}}
    <div class="edit">
        <a href="{{ url('posts/'.$post->id.'/edit') }}" class="btn btn-primary">
            {{ __('Edit') }}
        </a>
        @component('components.btn-del')
            @slot('table', 'posts')
            @slot('id', $post->id)
        @endcomponent
    </div>

    {{-- 記事内容 --}}
    <dl class="row">
        <dt class="col-md-2">{{ __('Created') }}:</dt>
        <dd class="col-md-10">
            <time itemprop="dateCreated" datetime="{{ $post->created_at }}">
                {{ $post->created_at }}
            </time>
        </dd>
        <dt class="col-md-2">{{ __('Updated') }}:</dt>
        <dd class="col-md-10">
            <time itemprop="dateModified" datetime="{{ $post->updated_at }}">
                {{ $post->updated_at }}
            </time>
        </dd>
    </dl>
    <hr>
    <div id="post-body">
        {{ $post->body }}
    </div>
</div>
@endsection
```

# 新規作成 (create, store)
![003.png](https://qiita-image-store.s3.amazonaws.com/0/27816/3935fd5a-d790-f1eb-d041-96f3a3652c09.png)

## コントローラ
```php:app/Http/Controllers/PostController.php
    public function create()
    {
        return view('posts.create');
    }

    public function store(Request $request)
    {
        $post = new Post;
        $post->title = $request->title;
        $post->body = $request->body;
        $post->save();
        return redirect('posts/'.$post->id);
    }
```

## ビュー
```html:resources/views/posts/create.blade.php
@php
    $title = __('Create Post');
@endphp
@extends('layouts.my')
@section('content')
<div class="container">
    <h1>{{ $title }}</h1>
    <form action="{{ url('posts') }}" method="post">
        @csrf
        @method('POST')
        <div class="form-group">
            <label for="title">{{ __('Title') }}</label>
            <input id="title" type="text" class="form-control" name="title" required autofocus>
        </div>
        <div class="form-group">
            <label for="body">{{ __('Body') }}</label>
            <textarea id="body" class="form-control" name="body" rows="8" required></textarea>
        </div>
        <button type="submit" name="submit" class="btn btn-primary">{{ __('Submit') }}</button>
    </form>
</div>
@endsection
```

# 更新 (edit, update)
![004.png](https://qiita-image-store.s3.amazonaws.com/0/27816/7a35b404-1834-2e30-89ac-edbc730919ba.png)

## コントローラ
```php:app/Http/Controllers/PostController.php
    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function edit(Post $post)
    {
        return view('posts.edit', ['post' => $post]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        $post->title = $request->title;
        $post->body = $request->body;
        $post->save();
        return redirect('posts/' . $post->id);
    }
```

## ビュー
```html:resources/views/posts/edit.blade.php
@php
    $title = __('Edit') . ': ' . $post->title;
@endphp
@extends('layouts.my')
@section('content')
<div class="container">
    <h1>{{ $title }}</h1>
    <form action="{{ url('posts/'.$post->id) }}" method="post">
        @csrf
        @method('PUT')
        <div class="form-group">
            <label for="title">{{ __('Title') }}</label>
            <input id="title" type="text" class="form-control" name="title" value="{{ $post->title }}" required autofocus>
        </div>
        <div class="form-group">
            <label for="body">{{ __('Body') }}</label>
            <textarea id="body" class="form-control" name="body" rows="8" required>{{ $post->body }}</textarea>
        </div>
        <button type="submit" name="submit" class="btn btn-primary">{{ __('Submit') }}</button>
    </form>
</div>
@endsection
```

# 削除 (destroy)
## コントローラ
```php:app/Http/Controllers/PostController.php
    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();
        return redirect('posts');
    }
```

## ビュー
showのビューで、削除ボタン用のコンポーネントを既に配置しています。