5️⃣

【Laravel10】 Inertia + React で「追加・変更・削除・閲覧」機能をつくる(その5)

2024/07/23に公開2

概要

【Laravel10】 Inertia + React で「追加・変更・削除・閲覧」機能をつくる(その4)の続編です。
現在、index,new,store,showアクションの実装が完了してる状態です。今回はedit,updateアクションを実装します。

バージョン情報

その1から同じなので、割愛

PostController::editを実装

コントローラ側

app/Http/Controllers/PostController.phpを編集

PostController.php
<?php

namespace App\Http\Controllers;

use App\UseCases\Post\IndexAction;
use App\UseCases\Post\StoreAction;
use App\UseCases\Post\FindAction;
use App\Http\Requests\Post\StoreRequest;
use App\Http\Requests\Post\FindRequest;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

class PostController extends Controller
{
    public function index(IndexAction $action): Response
    {
        return Inertia::render('Post/Index', $action());
    }

    public function new(): Response
    {
        return Inertia::render('Post/Create');
    }

    public function store(StoreRequest $request, StoreAction $action): RedirectResponse
    {
        $action($request);

        return redirect()->route('posts.view.index')->with([
            'message' => '登録が完了しました',
        ]);
    }

    public function show(FindRequest $request, FindAction $action): Response
    {
        return Inertia::render('Post/Show', $action($request));
    }

    public function edit(FindRequest $request, FindAction $action): Response
    {
        return Inertia::render('Post/Edit', $action($request));
    }

    public function update()
    {
    }

    public function destroy()
    {
    }
}

コンポーネント側

resources/js/Pages/Post/Edit.jsxを作成

resources/js/Pages/Post/Edit.jsx
import React from 'react';
import PostForm from "@/Components/Post/Form";

export default function Edit(props) {

    const { post, errors } = props;

    return (
        <PostForm type="edit" post={post} errors={errors}></PostForm>
    );

}

PostController::updateを実装

コントローラ側

app/Http/Requests/Post/UpdateRequest.phpを作成

php artisan make:request Post/UpdateRequest

app/Http/Requests/Post/UpdateRequest.phpapp/Http/Requests/Post/StoreRequest.phpは、同じバリデーションを利用したいので、次に親クラス(app/Http/Requests/Post/BaseStoreRequest.php)を切って、共通処理をまとめておく。

app/Http/Requests/Post/BaseStoreRequest.phpを作成

このファイルで、新規登録のリクエストと更新のリクエストの共通処理をまとめる。

app/Http/Requests/Post/BaseStoreRequest.php
<?php

namespace App\Http\Requests\Post;

use Illuminate\Foundation\Http\FormRequest;

class BaseStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
     */
    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:20'],
            'body' => ['required', 'string', 'max:1500'],
        ];
    }
}

app/Http/Requests/Post/StoreRequest.phpを編集

BaseStoreRequest.phpを継承する形に書き換える。

app/Http/Requests/Post/StoreRequest.php
<?php

namespace App\Http\Requests\Post;

use App\Models\Post;
use Illuminate\Foundation\Http\FormRequest;
use App\Http\Requests\Post\BaseStoreRequest;

class StoreRequest extends BaseStoreRequest
{
    public function makePost(): Post
    {
        return new Post($this->validated());
    }
}

app/Http/Requests/Post/UpdateRequest.phpを編集

BaseStoreRequest.phpを継承する形で実装する。

app/Http/Requests/Post/UpdateRequest.php
<?php

namespace App\Http\Requests\Post;

use App\Models\Post;
use Illuminate\Foundation\Http\FormRequest;
use App\Http\Requests\Post\BaseStoreRequest;

class UpdateRequest extends BaseStoreRequest
{
    /**
     * ルートIDから投稿データを取得
     */
    public function findPost(): Post
    {
        return Post::findOrFail($this->id);
    }
}

app/UseCases/Post/UpdateAction.phpを作成

app/UseCases/Post/UpdateAction.php
<?php

namespace App\UseCases\Post;

use App\Http\Requests\Post\UpdateRequest;

class UpdateAction
{
    public function __invoke(UpdateRequest $request): void
    {
        $post = $request->findPost();

        $post->title = $request['title'];
        $post->body = $request['body'];

        $post->save();
    }
}

app/Http/Controllers/PostController.phpを編集

app/Http/Controllers/PostController.php
<?php

namespace App\Http\Controllers;

use App\UseCases\Post\IndexAction;
use App\UseCases\Post\StoreAction;
use App\UseCases\Post\FindAction;
use App\UseCases\Post\UpdateAction;
use App\Http\Requests\Post\StoreRequest;
use App\Http\Requests\Post\FindRequest;
use App\Http\Requests\Post\UpdateRequest;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

class PostController extends Controller
{
    public function index(IndexAction $action): Response
    {
        return Inertia::render('Post/Index', $action());
    }

    public function new(): Response
    {
        return Inertia::render('Post/Create');
    }

    public function store(StoreRequest $request, StoreAction $action): RedirectResponse
    {
        $action($request);

        return redirect()->route('posts.view.index')->with([
            'message' => '登録が完了しました',
        ]);
    }

    public function show(FindRequest $request, FindAction $action): Response
    {
        return Inertia::render('Post/Show', $action($request));
    }

    public function edit(FindRequest $request, FindAction $action): Response
    {
        return Inertia::render('Post/Edit', $action($request));
    }

    public function update(UpdateRequest $request, UpdateAction $action): RedirectResponse
    {
        $action($request);

        return redirect()->route('posts.view.index')->with([
            'message' => '変更が完了しました',
        ]);
    }

    public function destroy()
    {
    }
}

確認

npm run dev をして、http://localhost/posts にアクセスして、任意の投稿で「変更」をクリックしてみてください。http://localhost/posts/:id/edit に遷移して編集画面に遷移することが確認できます。
編集画面送信するをクリックして、更新も上手く機能していることが確認できます。

残りは、投稿削除(PostController::destroy)のみです。
【Laravel10】 Inertia + React で「追加・変更・削除・閲覧」機能をつくる(その6)で、この部分を実装します。

関連記事

Discussion

Tomohiko MurakamiTomohiko Murakami

Reactが0の状態からnapojinさんのおかげで理解することができました。
ありがとうございます。

大変申し上げにくいのですが、更新が発生したタイミングでForm.jsxにputを追加する必要があるみたいでした。
const { data, setData, processing, post, put } = useForm({

それ以外は問題なく動作しています!