サイトアイコン 上尾市のWEBプログラマーによるブログ

「プロフェッショナルWebプログラミングLaravel」の感想・備忘録3

基本

編集画面の作成

1. sail artisan make:controller Tweet/Update/IndexController --invokable

namespace App\Http\Controllers\Tweet\Update;

use App\Http\Controllers\Controller;
use App\Models\Tweet;
use Illuminate\Http\Request;

class IndexController extends Controller
{
    /**
     * Handle the incoming request.
     */
    public function __invoke(Request $request): View
    {
        return view('tweet.update', ['tweet' => Tweet::where('id', (int)$request->route('id'))->firstOrFail()]);
    }
}

2. route/web.phpに追加

Route::get('/tweet/update/{id}', \App\Http\Controllers\Tweet\Update\IndexController::class)->name('tweet.update.index')->where('id', '[0-9]+');

3. touch resources/views/tweet/update.blade.php

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>つぶやきアプリ</title>
</head>
<body>
<h1>つぶやきを編集する</h1>
<div>
    <a href="{{ route('tweet.index') }}">< 戻る</a>
    <p>投稿フォーム</p>
    @if (session('feedback.success'))
        <p style="color: green">{{ session('feedback.success') }}</p>
    @endif
    <form action="{{ route('tweet.update.put', ['id' => $tweet->id]) }}" method="post">
        @method('PUT')
        @csrf
        <label for="tweet-content">つぶやき</label>
        <span>140文字まで</span>
        <textarea id="tweet-content" type="text" name="tweet" placeholder="つぶやきを入力">{{ $tweet->content }}</textarea>
        @error('tweet')
        <p style="color: red;">{{ $message }}</p>
        @enderror
        <button type="submit">編集</button>
    </form>
</div>
</body>
</html>

編集処理の作成

1. sail artisan make:controller Tweet/Update/PutController --invokable

<?php

namespace App\Http\Controllers\Tweet\Update;

use App\Http\Controllers\Controller;
use App\Http\Requests\Tweet\UpdateRequest;
use App\Models\Tweet;
use App\Services\TweetService;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\Response;

class PutController extends Controller
{
    /**
     * Handle the incoming request.
     * @param UpdateRequest $request
     * @param TweetService $tweetService
     * @return Response
     */
    public function __invoke(UpdateRequest $request, TweetService $tweetService): Response
    {
        if (!$tweetService->isOwnTweet($request->user()->id, $request->id())) {
            throw new AccessDeniedException();
        }
        $tweet = Tweet::where('id', $request->id())->firstOrFail();
        $tweet->content = $request->tweet();
        $tweet->save();
        return redirect()
            ->route('tweet.update.index', ['id' => $tweet->id])
            ->with('feedback.success', 'つぶやきを編集しました。');
    }
}

2. route/web.phpに追加

Route::put('/tweet/update/{id}', \App\Http\Controllers\Tweet\Update\PutController::class)->name('tweet.update.put')->where('id', '[0-9]+');

3. sail artisan make:request Tweet/UpdateRequest

<?php

namespace App\Http\Requests\Tweet;

use Illuminate\Foundation\Http\FormRequest;

class UpdateRequest 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 [
            'tweet' => 'required|max:140'
        ];
    }

    public function tweet(): string
    {
        return $this->input('tweet');
    }

    public function id(): int
    {
        return (int)$this->route('id');
    }
}

4. resources/views/tweet/update.blade.phpに以下を追加

@if (session('feedback.success'))
    <p style="color: green">{{ session('feedback.success') }}</p>
@endif

削除処理の作成

1. sail artisan make:controller Tweet/DeleteController --invokable

<?php

namespace App\Http\Controllers\Tweet;

use App\Http\Controllers\Controller;
use App\Models\Tweet;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\Response;

class DeleteController extends Controller
{
    /**
     * Handle the incoming request.
     * @param Request $request
     * @return Response
     */
    public function __invoke(Request $request, TweetService $tweetService): Response
    {
        if (!$tweetService->isOwnTweet($request->user()->id, $request->id())) {
            throw new AccessDeniedException();
        }
        $tweet = Tweet::where('id', (int)$request->route('id'))->firstOrFail();
        $tweet->delete();
        return redirect()
            ->route('tweet.index')
            ->with('feedback.success', 'つぶやきを削除しました。');
    }
}

2. route/web.phpに追加

Route::delete('/tweet/delete/{id}', \App\Http\Controllers\Tweet\DeleteController::class)->name('tweet.delete');

3. resources/views/tweet/index.blade.phpに以下を追加

@if (session('feedback.success'))
    <p style="color: green">{{ session('feedback.success') }}</p>
@endif
モバイルバージョンを終了