laravel9で記事投稿機能を作ってみた

## はじめに
こんにちは！
自分は、エンジニアとして就職するため、日々戦っているフリーターです:bow_tone3:

現在、インターン・アルバイト・就活に向けてポートフォリオをlaravel9で作成しており、作った機能などを順に投稿していこうと思います

自分のアウトプットがメインですが、laravelでポートフォリオなどを作ろうとしている人の、少しでも役に立てれば幸いです:fist_tone2:

ログインシステムやシンボリックリンクなどが実装された前提です
## 開発環境
細かい機能や技術はポートフォリオ完成後に総じて書こうと思います
* PHP:8.0.2
* Laravel:9.19
* composer:2.2
* MySQL:8.0
* nginx:1.20
* docker

## migration
migrationファイルは各自のコンセプトに合わせて作成してください！
```
public function up()
    {
        Schema::create('problem_articles', function (Blueprint $table) {
            $table->unsignedBigInteger('id', true);
            $table->unsignedBigInteger('user_id');
            $table->string('user_name');
            $table->string('title');
            $table->string('name')->nullable();
            $table->string('path')->nullable();
            $table->longText('content');
            $table->timestamps;
            $table->foreign('user_id')->references('id')->on('users');
        });
    }

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

## web.php
```
// ↓は投稿機能のフォームを表示するURL
Route::get('/create', function () {
        return view('article_create');
    });

// ↓は投稿記事のデータをControllerで処理する際に用いるURL
Route::post('/store', [ProblemArticleController::class, 'store'])->name('store');
```
/createは投稿のフォームを表示させたいので、Route::getで、article_create.blade.phpを読み込むように書いています。

/storeは、データを送るためRoute::postにしています。/createで表示しているarticle_create.blade.phpの投稿フォームにユーザが入力してデータを送信した時、用いるURLです。

## ProblemArticleController
Controllerでは、article_create.blade.phpで送られたデータをProblemArticleテーブルに保存する処理などをしています。
```
<?php
namespace App\Http\Controllers;

use App\Models\ProblemArticle;

class ProblemArticleController extends Controller
{
    public function store(Request $request)
        {
            // インスタンス化
            $problemArticle = new ProblemArticle();
            // タイトル
            $problemArticle->title = $request->input('title');
            // テキスト
            $problemArticle->content = $request->input('content');

            // \Auth::idはログインしているユーザーのデータが入る
            $problemArticle->user_id = \Auth::id();
            $problemArticle->user_name = \Auth::user()->name;
            // ここからは画像処理
            $image = $request->file('image');
            if($image){
                $file = $request->file('image');
    
                $file_name = $file->getClientOriginalName();
                $file->storeAs('public/' , $file_name);
    
                $problemArticle->name = $file_name;
                $problemArticle->path = 'storage/' . $file_name;
            }
            // 保存
            $problemArticle->save();
            
            // 処理が終わった後、用意したhome.blade.phpにリダイレクトする
            return redirect (route('home'));
        }
}
```

例えば、
viewで用意した【input name="title"】にユーザが入力して送信した場合、そのデータは、
problemArticle->title = $request->input('title');
↑この部分でテーブルに保存する処理をしています！

```
$image = $request->file('image');
// もし画像ファイル($image)があった場合以下の処理が行われる
if($image){
    // ユーザが送ったファイルを受け取る
    $file = $request->file('image');
    // アップロードしたファイルのファイル名を取得
    $file_name = $file->getClientOriginalName();
    // public/にアップロードしたファイル名を保存
    $file->storeAs('public/' , $file_name);

    // ProblemArticleテーブルに保存
    $problemArticle->name = $file_name;
    $problemArticle->path = 'storage/' . $file_name;
}
```
↑は画像処理の部分ですが、いらない人は飛ばしてください。

## article_create.blade.php
ここはユーザに見える部分で、以下がviewの部分になります！
```php:article_create.blade.php
<div class="create_area">
    <form action="{{ route('store') }}" method="POST" enctype="multipart/form-data">
    @csrf
        <p class="name">新規投稿</p>
        <div class="text_area">
            <div class="title_area">
                <input type="title" class="title" id="" placeholder="タイトル" name="title">
            </div>
            <div class="file_area">
                <input type="file" class="file" name="image">
            </div>
            <div class="content_area">
                <textarea class="content" placeholder="悩み" id="" name="content"></textarea>
            </div>
        </div>
        <div class="button_area">
            <button type="submit" class="post">投稿</button>
        </div>
    </form>
    </div>
```
以下で/storeにPOSTするように定義しており、csrfトークンを送るようにしないと419エラーが出ます。
```
<form action="{{ route('store') }}" method="POST" enctype="multipart/form-data">
@csrf
```