"Blade로 Chirper 구축 - Chirps 편집"의 두 판 사이의 차이

198번째 줄: 198번째 줄:


==테스트하기==
==테스트하기==
[[파일:chirp-editted-blade.png|640px]]

2024년 6월 18일 (화) 22:04 판

1 개요

05. Editing Chirps
05. Chirps 편집

https://bootcamp.laravel.com/blade/editing-chirps

다른 인기 있는 마이크로블로깅 플랫폼에 누락된 기능을 추가해 보겠습니다 — 바로 'Chirps'를 수정할 수 있는 기능입니다!

2 라우팅

먼저 리소스 컨트롤러에 대해 chirps.editchirps.update 라우트를 활성화하려면 라우트 파일을 업데이트합니다. chirps.edit 라우트는 Chirp를 편집하는 폼을 표시하며, chirps.update 라우트는 폼에서 데이터를 받아 모델을 업데이트합니다:

routes/web.php
<?php
...
Route::resource('chirps', ChirpController::class)
    ->only(['index', 'store', 'edit', 'update'])
    ->middleware(['auth', 'verified']);
...

이 컨트롤러에 대한 라우트 테이블은 이제 다음과 같습니다:

Verb URI Action Route Name
GET /chirps index chirps.index
POST /chirps store chirps.store
GET /chirps/{chirp}/edit edit chirps.edit
PUT/PATCH /chirps/{chirp} update chirps.update

3 편집 페이지 링크 걸기

다음으로, chirps.edit 라우트로 링크를 겁니다. Breeze와 함께 제공되는 x-dropdown 컴포넌트를 사용하여, 이를 Chirp 작성자에게만 표시합니다. 또한, Chirp의 created_at 날짜와 updated_at 날짜를 비교하여 Chirp가 수정된 경우 표시합니다:

resources/views/chirps/index.blade.php
<x-app-layout>
    <div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
        <form method="POST" action="{{ route('chirps.store') }}">
            @csrf
            <textarea
                name="message"
                placeholder="{{ __('What\'s on your mind?') }}"
                class="block w-full border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm"
            >{{ old('message') }}</textarea>
            <x-input-error :messages="$errors->get('message')" class="mt-2" />
            <x-primary-button class="mt-4">{{ __('Chirp') }}</x-primary-button>
        </form>
 
        <div class="mt-6 bg-white shadow-sm rounded-lg divide-y">
            @foreach ($chirps as $chirp)
                <div class="p-6 flex space-x-2">
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-600 -scale-x-100" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
                    </svg>
                    <div class="flex-1">
                        <div class="flex justify-between items-center">
                            <div>
                                <span class="text-gray-800">{{ $chirp->user->name }}</span>
                                <small class="ml-2 text-sm text-gray-600">{{ $chirp->created_at->format('j M Y, g:i a') }}</small>
                                @unless ($chirp->created_at->eq($chirp->updated_at))
                                    <small class="text-sm text-gray-600"> &middot; {{ __('edited') }}</small>
                                @endunless
                            </div>
                            @if ($chirp->user->is(auth()->user()))
                                <x-dropdown>
                                    <x-slot name="trigger">
                                        <button>
                                            <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-gray-400" viewBox="0 0 20 20" fill="currentColor">
                                                <path d="M6 10a2 2 0 11-4 0 2 2 0 014 0zM12 10a2 2 0 11-4 0 2 2 0 014 0zM16 12a2 2 0 100-4 2 2 0 000 4z" />
                                            </svg>
                                        </button>
                                    </x-slot>
                                    <x-slot name="content">
                                        <x-dropdown-link :href="route('chirps.edit', $chirp)">
                                            {{ __('Edit') }}
                                        </x-dropdown-link>
                                    </x-slot>
                                </x-dropdown>
                            @endif
                        </div>
                        <p class="mt-4 text-lg text-gray-900">{{ $chirp->message }}</p>
                    </div>
                </div>
            @endforeach
        </div>
    </div>
</x-app-layout>

4 편집 폼 생성하기

Chirp를 편집하기 위한 새 Blade 뷰를 만들어봅시다. 이는 Chirp를 생성하기 위한 폼과 유사하지만, chirps.update 라우트로 포스트하고, @method 지시어을 사용하여 "PATCH" 요청을 보냅니다. 또한, 기존의 Chirp 메시지로 필드를 미리 채워넣습니다:

resources/views/chirps/edit.blade.php
<x-app-layout>
    <div class="max-w-2xl mx-auto p-4 sm:p-6 lg:p-8">
        <form method="POST" action="{{ route('chirps.update', $chirp) }}">
            @csrf
            @method('patch')
            <textarea
                name="message"
                class="block w-full border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md shadow-sm"
            >{{ old('message', $chirp->message) }}</textarea>
            <x-input-error :messages="$errors->get('message')" class="mt-2" />
            <div class="mt-4 space-x-2">
                <x-primary-button>{{ __('Save') }}</x-primary-button>
                <a href="{{ route('chirps.index') }}">{{ __('Cancel') }}</a>
            </div>
        </form>
    </div>
</x-app-layout>

5 컨트롤러 업데이트하기

ChirpController의 edit 메소드를 업데이트하여 폼을 표시하도록 합시다. Laravel은 라우트 모델 바인딩을 사용하여 데이터베이스에서 Chirp 모델을 자동으로 로드하므로 이를 바로 뷰에 전달할 수 있습니다.

그 후, update 메소드를 업데이트하여 요청을 검증하고 데이터베이스를 업데이트하도록 합시다.

Chirp의 작성자에게만 편집 버튼을 표시하고 있지만, 이러한 라우트에 접근하는 사용자가 권한을 가지고 있는지 확인할 필요가 있습니다:

app/Http/Controllers/ChirpController.php
<?php
...
use Illuminate\Support\Facades\Gate;
use Illuminate\View\View;
 
class ChirpController extends Controller
{
    ...
    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Chirp $chirp): View
    {
        //
        Gate::authorize('update', $chirp);
 
        return view('chirps.edit', [
            'chirp' => $chirp,
        ]);
    }
    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, Chirp $chirp): RedirectResponse
    {
        //
        Gate::authorize('update', $chirp);
 
        $validated = $request->validate([
            'message' => 'required|string|max:255',
        ]);
 
        $chirp->update($validated);
 
        return redirect(route('chirps.index'));
    }
    ...

Note

아마도 유효성 검증 규칙이 store 메소드와 중복된 것을 알아차렸을 것입니다. Laravel의 폼 요청 유효성 검증을 사용하여 이를 추출하는 것을 고려해볼 수 있습니다. 이는 유효성 검증 규칙을 재사용하기 쉽게 만들고 컨트롤러를 가볍게 유지하는 데 도움이 됩니다.

6 인가

기본적으로, authorize 메소드는 모든 사용자가 Chirp를 업데이트하지 못하도록 합니다. Chirp를 업데이트할 수 있는 사용자를 지정하려면 다음 명령어로 모델 정책을 생성합니다:

php artisan make:policy ChirpPolicy --model=Chirp

이 명령어는 app/Policies/ChirpPolicy.php에 정책 클래스를 생성합니다. 이 파일을 업데이트하여 작성자만 Chirp를 업데이트할 수 있도록 지정할 수 있습니다:

app/Policies/ChirpPolicy.php
<?php
...
class ChirpPolicy
{
    ...
    /**
     * 사용자가 모델을 업데이트할 수 있는지 결정합니다.
     */
    public function update(User $user, Chirp $chirp): bool
    {
        return $chirp->user()->is($user);
    }
    ...
}

7 테스트하기

Chirp-editted-blade.png

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}