Laravelで投稿一覧を表示、一意のURLをつけて表示するまで。備忘録

Laravelにてただいま絶賛webアプリ作成中なのですが、久しぶりに備忘録を書こうと思います。
userが投稿してそれを全体のページに表示するのと、その表示したページにアクセスして一意（表現があっているかわからないけど）のURLを作成してアクセスするところまでできたので備忘録にて記載したいと思います。
自分でも備忘録を記載しているついでに微妙なコードがあったら直したいので、、

処理の流れとしては
1.userがログイン後/articleページに移動する。
2.articleの投稿ボタンが押下されたら、自身のページとトップページに投稿内容を表示する。
3.投稿内容をクリックもしくはタッチするとその一意ページに飛ぶ。


<h2>1．userがログイン後/articleページに移動する。</h2>

![article投稿.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/826735/acbd77bb-f338-b43c-61dc-bfec320d7446.png)


かなりシンプルな見た目にはなっているのですが、とりあえず動いてなんぼだと思っているので、ご愛敬という事で、、
適当にテスト！！！と打ち、記事を追加するを押下します。

![user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/826735/46ab4902-c7b7-997e-4910-c02436ab17f7.png)

全体ページの「テスト!!!」を押下すると、



するとuser自身のページと全体のページに投稿が反映されています。これがユーザー自身のページ。下が全体ページとなります。

![全体.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/826735/fc764a19-a3b0-1462-67de-ed7bf1d35337.png)


![一意ページ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/826735/11848642-4ba7-2bb2-1e25-7a0fe70e4ddc.png)
一意のURLを持ったページが表示されます。


とりあえず上記で使っているファイル一覧が以下

<h3>ビューファイル一覧</h3>
<ul>
<li>voting.blade.php(全体ページのビューファイル)</li>
<li>home.blade.php(user自身のページのビューファイル)</li>
<li>article.blade.php(投稿するためのページのビューファイル)</li>
<li>article_display.php(投稿結果の一意のURL(id)を持つビューファイル)</li>
</ul>

<h3>コントローラファイル一覧</h3>
<ul>
<li>VotinCotroller.php</li>
<li>UserController.php</li>
<li>ArticleController.php</li>
</ul>


<h3>テーブルファイル一覧</h3>
<ul>
<li>user_creates_table</li>
<li>article_creates_table</li>
<li>create_votings_table</li>
</ul>

<h3>モデルファイル一覧</h3>
<ul>
<li>User.php</li>
<li>Article.php</li>
<li>Voting.php</li>
</ul>

なおルーティングファイルはweb.phpとなります。

articleの処理

```php:User.php
   public function articles(){
        /**
         * リレーション一対多の一側
         * user(1):article(多)
         * articleテーブルを新しい順で更新する。
         * 
         * 
           */
        return $this->hasMany('App\Models\Article')->latest();
    }
```




```php:Article.php
  
    /**
     * 一対多の多側、article
     * votingとarticleのリレーション
    */
    public function voting(){
        return $this->belongsTo('App\models\Voting');
    }
```
articleはuserと一体多の関係なのでリレーションします。
userが一でarticleが多です。
リレーションについては別の機会に記載したいと思います。
これがリレーションの根幹となります。

```php:UserController.php
public function show(User $user)
    {
        /**
         * $userによる投稿を取得
         * 投稿作成日が新しい順に並べる。
         * articleのpagenateをユーザー自身のページを5ページ
         * */ 
        $user->articles = $user->articles()->paginate(5);
        return view('users.show', ['user' => $user]);     
    }
```
$userのarticleカラムに投稿内容を追加してpagenateしています。
その後、return　viewでusers.showを表示しています。

```php:Article.Controller
public function store(Request $request){
        $article = new Article();
        /** 
        * バリデーションを設定する。
        */
        $validator = Validator::make($request->all(), [
            /* 入力必須255文字 form のarticleのバリデーションチェック*/
            'article' => 'required|max:255',
        ]);
        if ($validator->fails()) {
            return redirect('/article')
                ->withInput()
                ->withErrors($validator);    
        }
        /**
         * 以下はブレードファイルのarticleのnameを指定して値をとっている。
         * この処理はarticleの内容を保存している。
         * ->articleはカラム
         * articleのidが表示される。
         */  
        $article->user_id = $request->user()->id;
        /**
         * 上記の$article->user_idはarticleのユーザーid格納カラム。
         *articleのタイトルをテーブルから呼び出して$article->article_title 
        */
        $article->article = $request->article;
        /**articleが投稿された時点でidは発行されているのでそこに紐づけしたい。
         * 例:
         * "user_id" => 3
         * "article" => "ｄｄ"
         * "updated_at" => "2021-01-05 03:11:39"
         * "created_at" => "2021-01-05 03:11:39"
         * "id" => 34←これをURLにする。
         * 
        */  
        $article->save();    
        return redirect(("/home"));
    }

```
articleをnewします。
その下でバリデーションしています。ここで入力判定して文字を入力しないで投稿ボタンを押すと入力してくださいと表示されarticleにredirectします。

```php:ルーティングweb.php
Route::post('/article',  [App\Http\Controllers\ArticleController::class, 'store'])->name('articlepost');

```
上記でコントローラを呼び出しarticle_post->nameしてarticle.blade.phpで呼び出しています。

```php:

$article->user_id = $request->user()->id;
```

```php:article.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="col-sm-offset-2 col-sm-8">
        <div class="panel panel-default">
            <div class="panel-body">
                @include('common.errors')
                <form action="{{ route('articlepost')}}"  method="POST" class="form-horizontal">
                   {{ csrf_field() }}
                   <div class="form-group">
                       <label for="task-name" class="col-sm-3 control-label">記事を以下に書く</label>
                　　   <!-- タイトル、本文 -->
                　　    <div class="form-group">
                           <div class="col-sm-6">
                              <textarea rows="10" cols="100" name="article" name="contents" class= "form-control" id="message" style="resize:none"></textarea> 
                           </div>
                　　     </div>
                         <div class="form-group">
                            <div class="col-sm-offset-3 col-sm-6">
                                <button type="submit" class="btn btn-default">
                                    <i class="fa fa-plus"></i>記事を追加する
                                </button>
                            </div>
                         </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <!-- ここからユーザー自身が書いたarticleを表示する。 -->
</div>
@endsection
```
上記が投稿するためのarticleのviewです。

```php:home.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card" class="col-sm-offset-2 col-sm-8">
                <div class="card-header">{{ __('Dashboard') }}</div>
                <div class="card-body">{{ Auth::user()->name }}</div>
                <div class="card-body">{{ Auth::user()->email }}</div>
                <div class="card-body">{{ Auth::user()->id }}</div>
                <!-- ここにユーザーの記事一覧を表示する。 -->
                <table class="table table-striped">
                <thead>
                    <tr>
                        <th>{{ __('Author') }}</th>
                        <th>{{ __('article') }}</th>
                    </tr>
                    <!-- ログイン中のユーザー=user その中のarticles -->
                    @foreach($user -> articles as $article)
                        <tr>
                            <td>
                                <!-- usernameを出力する -->
                                {{$user->name}}
                            </td>
                            <td>
                                <!-- articleテーブルのarticletitleに変更 -->
                               
                                {{$article->article}}
                            </td>
                        </tr>
                    @endforeach
                </thead>
                </table>

                <form action="/">
                    <button type="submit" class="btn btn-light">みんなの記事一覧へ</button>
                </form>
                <a href="/article"><button type="submit" class="btn btn-light">記事作成ページへ移動する。</button></a>

                <!-- ユーザー情報を削除ボタン押したらtopに戻る。補足:できればパスワードを要求するusercontrolerを使うか?homeからできるならやる -->
                <!-- 削除ボタンを作る -->
                <!-- actionでurl指定している。ユーザーのidを表示できる-->
                <!-- ボタンを押すと画面が遷移できるので処理はrouteは呼べているが、削除ができない。 -->
                <!-- ここのuseridはコントローラのuseridを示している -->
                <form action="{{ route('user_delete')}}" method="post" id="user_delete_form">
                    @method('DELETE')
                    @csrf                
                    <button type="submit" class="btn btn-danger" onclick="return confirm('Okボタンを押すとすべてのユーザー情報を削除してしまい、復活もできません。よろしいですか？')">
                    <i class="fa fa-trash">{{ __('ユーザー情報を削除する。') }}</i>       
                    </button>
                </form>
                <!--  -->
                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    {{ __('ログインされています。') }}
                </div>
            </div>
        </div>      
    </div>
    <div class="d-flex justify-content-center mb-5">{{$user->articles->links()}}</div>
</div>
@endsection
```
上記がuserのページです。home.blade.phpとなっているので少しややこしいですが、、


saveを使って保存し、自身のページにredirectします。
以上が投稿を保存しuserのページ一覧に表示する流れです。
続いて全体ページに表示する処理です。

```php:VotingController
  public function index(User $user)
    {
        
        /** 
         * 新しい順で表示する。
         */
        $articles = Article::select(['article','user_id','id'])->orderBy('created_at', 'desc')->get();    
        return view('votings', [
            'articles' => $articles
            ]);
    }

```
これもわかりづらいですが、votingが全体ページの根幹です。
Articleの中に紐づくarticle,user_id,'id'を$articlesを代入しています。
新しい順に取得し表示するために->orderBy('created_at', 'desc')->get();    
 としています。

```php:voting.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
    <div class="col-sm-offset-2 col-sm-8">
        <div class="panel panel-default">
            <div class="panel-heading">
                記事一覧
            </div>
    
        </div>
        <!-- 記事一覧 -->
        @if (count($articles)>0)
           <div class="panel-body">
               <div class="panel-heading">
                記事一覧
               </div>
               <div class="panel-body">
                   <table class="table table-striped task-table">
                       <thead>
                           <th>記事</th>
                           <th>&nbsp;</th>
                        </thead>
                       <tbody>
                           @foreach ($articles as $article)
                              <tr>
                
                                  <!-- ここにurlの投稿一覧を表示する -->
                                  <!-- 以下にaタグをつかってとりあえずarticle_idをddできるようにする。
                                  接続するにはまずコントローラ側で/article/{id}で指定しなければならない。 
                                  'id' => $article->id←これでarticleのidを取得している。
                                  -->
                                  <td class="table-text">
                                     <div class="table-text">
                                         <a href = "{{ route('article_display', ['id' => $article->id])}}">
                                            {{ $article->article }}
                                         </a>
                                     </div>
                                  <td class="table-text"><div class="table-text">{{ $article->user_id }}</div></td>
                                  <td class="table-text"><div class="table-text">{{ $article->id }}</div></td>
                            　</tr>
                            @endforeach
                        </tbody>
                    </table>      
                </div>
            </div>
        @endif
        
       
    </div>
    {{-- ページネーション --}}
      
</div>
@endsection
```

```php:VotingController
return view('votings', [
            'articles' => $articles
            ]);
```
ここでvotingのビューにarticlesのプロパティを渡しています。

```php:voting.blade.php
<tbody>
                           @foreach ($articles as $article)
                              <tr>
                
                                  <!-- ここにurlの投稿一覧を表示する -->
                                  <!-- 以下にaタグをつかってとりあえずarticle_idをddできるようにする。
                                  接続するにはまずコントローラ側で/article/{id}で指定しなければならない。 
                                  'id' => $article->id←これでarticleのidを取得している。
                                  -->
                                  <td class="table-text">
                                     <div class="table-text">
                                         <a href = "{{ route('article_display', ['id' => $article->id])}}">
                                            {{ $article->article }}
                                         </a>
                                     </div>
                                  <td class="table-text"><div class="table-text">{{ $article->user_id }}</div></td>
                                  <td class="table-text"><div class="table-text">{{ $article->id }}</div></td>
                            　</tr>
                            @endforeach
                        </tbody>
                    </table>      
```

ここでarticle一覧を取得し、表示している。

とりあえず今日は以上です。コードも粗い部分がありますが、徐々に調整したいと思います。なにか間違いがあればご指摘頂ければと思います。