入社7日目とりあえず2ch掲示板に機能を実装してみるpart2

# ルーティング設定

routes/web.php にアクセスがあった時の処理を記述する。

    use App\Http\Controllers\ThreadController;
    
    Route::get('/', [ThreadController::class, 'index']);
    Route::resource('threads', ThreadController::class);

use App\Http\Controllers\ThreadController;
この階層にあるコントローラーを使うよ

'/'にアクセスした時に
ThreadControllerのclassである 'index'を使うよ。

# ビュー作成

resources/viewsのディレクトリ（フォルダ）の中に
threads ディレクトリを作成して下記3つを作成

threads/index.blade.php
threads/create.blade.php
threads/show.blade.php

それぞれの中に記述する。

### index.blade.php
    @extends('layouts.app')
    
    @section('content')
    <h1>スレッド一覧</h1>
    <a href="{{ route('threads.create') }}">スレッドを作成</a>
    <ul>
        @foreach ($threads as $thread)
            <li><a href="{{ route('threads.show', $thread->id) }}">{{ $thread->title }}</a></li>
        @endforeach
    </ul>
    @endsection


@extends('layouts.app')

このテンプレートファイルは同じ階層のlayouts/app.blade.phpを継承
layouts/app.blade.phpは共通部品の定義。

    @section('content')
@yield('content')に挿入

    <a href="{{ route('threads.create') }}">スレッドを作成</a>

aタグはリンクのHTMLタグ。

    {{ route('threads.create') }}


route関数でthreads.createをURLとして作成

リンクさせる。


    <ul>
はリストつくるよ〜のタグ


    @foreach ($threads as $thread)

foreachは繰り返すよ。
何を？
$threadsという変数に含まれているデータ一つずつ。
1件ずつは$threadという変数に格納して処理するよ。

$threads(a,b,c,d,e)

1回目thread(a)で処理
終わったら
2回目thread(b)で処理
・・・


        <li><a href="{{ route('threads.show', $thread->id) }}">{{ $thread->title }}</a></li>

liリストにするよー
リストはリンクにするよ。
route関数を使ってthreads.showというURLを$threadのid情報も渡して作成。
/threads/(id番号)に変換。

    <a href="">文字入れられる</a>
文字入れられる場所に

    {{ $thread->title }}

$threadに格納されているtitleに対応する値を呼び出し当て込む。

        @endforeach

繰り返しがなくなったら終わりだ。

    @endsection

ここで@yield('content')も終わり。



### creat.blade.php

これはスレッドの作成ページ

    @extends('layouts.app')
    
    @section('content')
    <h1>スレッド作成</h1>
    <form method="POST" action="{{ route('threads.store') }}">
        @csrf
        <label for="title">タイトル</label>
        <input type="text" name="title" id="title" required>
        <button type="submit">作成</button>
    </form>
    @endsection


これも同じだね

    @extends('layouts.app')

を継承

    @section('content')

@yield('content')の場所に入れ込むよ



    <form method="POST" action="{{ route('threads.store') }}">
    @csrf
    <label for="title">タイトル</label>
    <input type="text" name="title" id="title" required>
    <button type="submit">作成</button>
    </form>

formは送信用のタグ。
method="POST"はサーバーに送信するための方法。ここを"get"にするとURLに文字が出てくる。

    action="{{ route('threads.store') }}"

フォームの送信先のURLはthreads.store
web.phpのthreads.storeという名前付きルートを使う。
ここでちょっと引っかかる。

Route::post~~~~~
でthreads.storeなんて設定していない。

が

    Route::resource('threads', ThreadController::class);


を指定することでCRUDの操作に必要なルートが自動生成される。
なのでその中にthreads.storeも含まれていた。


    @endsection

それでここまでだよ〜といれて終わり。

    ## show.blade.php

次はスレッドの詳細ページの作成
    
    @extends('layouts.app')
    
    @section('content')
    <h1>{{ $thread->title }}</h1>
    <ul>
        @foreach ($posts as $post)
            <li>{{ $post->content }}</li>
        @endforeach
    </ul>
    <form method="POST" action="{{ route('posts.store') }}">
        @csrf
        <input type="hidden" name="thread_id" value="{{ $thread->id }}">
        <textarea name="content" rows="3" required></textarea>
        <button type="submit">投稿</button>
    </form>
    @endsection

これも見ていく

    @extends('layouts.app')
    
    @section('content')
    <h1>{{ $thread->title }}</h1>

h1タグにタイトルを表示。

    <ul>
        @foreach ($posts as $post)
            <li>{{ $post->content }}</li>
        @endforeach
    </ul>
リスト作成して。
foreachで繰り返し。
$postsを繰り返すよ。その時$postに入れて動かすよ。
$postの中のcontentを出して表示。



    <form method="POST" action="{{ route('posts.store') }}">

フォーム送信時にPOSTメソッドで送信。
routeでposts.storeのURLを作成してweb.phpに渡す。

    @csrf
なんだコレ

    CSRF（Cross-Site Request Forgery）保護機能を有効にします。

なんとなく理解。
ランダムなトークンが一つ生成されて、その値が一致しないとサーバーを書き換えられないようにする仕組みらしい。

ログイン中であるアプリケーションに対して、クッキーが自動的に送信するブラウザの動作を悪用している攻撃を防ぐらしい。
クッキー情報が入ったとしてもトークンが一致しないため、送信を失敗させる仕組みとのこと。

もっと深い気がするが一旦、セキュリティといった形で進める。



    <input type="hidden" name="thread_id" value="{{ $thread->id }}">

スレッドのIDを送信するよ。でもユーザーには見えないように隠すよ。

    <textarea name="content" rows="3" required></textarea>

サーバーに送信する時のデータ名はcontent。
rows="3"はテキストエリア3行分。

requiredは入力必須項目。

    
    <button type="submit">投稿</button>
    </form>
    @endsection

ボタンを押すとフォームデータをactionが指定したURLに送信。


ここまででユーザー側が見る画面を作成できた。

# スレッド作成機能の実装

## ルーティング設定
これはRoute::resouceで定義済み。

## コントローラーにメソッドを追加

ThreadController.php


    public function create()
        {
            return view('threads.create');
        }
    
        // 新しいスレッドをデータベースに保存する
        public function store(Request $request)
        {
            // バリデーションを実行
            $request->validate([
                'title' => 'required|max:255', // タイトルは必須で最大255文字
            ]);
    
            // データベースに保存
            Thread::create([
                'title' => $request->input('title'),
            ]);
    
            // スレッド一覧ページにリダイレクト
            return redirect()->route('threads.index')->with('success', 'スレッドを作成しました！');
        }

　

    public function create()

createメソッド
  
        return view('threads.create');

viewのthreads.createを開く



    public function store(Request $request)

Route::resourceで作成されたstoreで反応。

    Request $request

フォームからのデータを$requestにいれる。

        $request->validate

下記のルールに沿っているか確認。

    'title' => 'required|max:255', // タイトルは必須で最大255文字

タイトルは必ず必要で文字数制限255まで
        
        Thread::create()

Threadテーブルに新しいデータ入れますよ。


            'title' => $request->input('title'),
        ]);

$requestの中のtitleをtitleにいれるよ


        return redirect()->route('threads.index')->with('success', 'スレッドを作成しました！');
    }

スレッドが作成されました。
と一緒にthreads.indexにリダイレクト。

# ビューの作成

### create.blade.phpを作る

    @extends('layouts.app')
    
    @section('content')
        <h1>スレッドを作成</h1>
    
        <!-- エラーメッセージの表示 -->
        @if ($errors->any())
            <div>
                <ul>
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif
    
        <!-- スレッド作成フォーム -->
        <form method="POST" action="{{ route('threads.store') }}">
            @csrf
            <label for="title">スレッドタイトル</label>
            <input type="text" name="title" id="title" value="{{ old('title') }}" required>
            <button type="submit">作成</button>
        </form>
    @endsection

もうほとんど同じ繰り返しだ

ただ、エラーが出てくる文がある。
バリデーションエラーが発生した場合のものだった。
これの理由はPOST/Threadsに送信される。

入力ミスがあった場合エラー発生。

$errorsオブジェクトとしてテンプレートに渡される。
これを表示させるためのもの。

ModelsのThread.phpに

    protected $fillable = ['title'];

を入れる。
これでtitle以外の追加はできなくなる。

これで一通り完成した。。。

が
全然動かなかった。

    $slot

が定義されてないとひたすらでてGPTだとひたすらループの確認作業が始まったのであった。