이전 포스트는 내용이 비교적 짧았는데, 오늘의 포스트에서는 해야 할 일이 많다.
글을 보며 따라 하는 입장에서는 금방 할 수 있을지도 모르지만, 글을 쓰는 입장에서는 글을 쓰는 시간이 굉장히 많이 걸린다.
나의 글을 봐주는 사람이 분명 있기는 있을 텐데, 이런 글 하나 쓰는 데에 시간이 굉장히 많이 걸린다는 것을 알아줬으면 좋겠다.
어쨌든 이번에는 정말로 글 수정 기능을 구현해 보겠다.
이전 포스트
Laravel 글 작성자의 IP 주소 저장하기
글 수정 기능 구현 · 4th-avenue/laravel13-livewire@c1375d1 · GitHub
전체적인 코드 수정은 이 깃허브 링크를 통해서 확인할 수 있다.
Livewire 컴포넌트 pages::articles.edit 생성 (--mfc 옵션)
make bash #컨테이너 안으로 들어간다.
php artisan make:livewire pages::articles.edit --mfc
ubuntu 혹은 VSCode의 터미널에서 이 명령어들을 실행한다.
이번에도 show 컴포넌트를 만들었을 때처럼 --mfc 옵션을 넣어보았다.
Livewire 버전 4에서 컴포넌트 생성하기 (pages::articles.list 컴포넌트 생성)
--mfc 옵션에 대한 자세한 내용은 이 포스트를 참고하자.
routes/web.php에서 라우팅 설정하기
routes/web.php
Route::middleware('auth')->group(function () {
Route::view('profile', 'profile')->name('profile');
Route::livewire('articles/new', 'pages::articles.new')->name('articles.new');
// 추가
Route::livewire('articles/{article:id}/edit', 'pages::articles.edit')->name('articles.edit');
});
라우팅 설정을 했다.
다른 코드들은 원래 있던 코드고, // 추가라는 주석 바로 아래의 한 줄만 새로 추가됐다.
로그인한 사용자만 글 수정 페이지에 접근할 수 있도록 라우트 그룹 내부에 코드를 추가했다.
라라벨 Livewire 4 컴포넌트의 web.php 라우팅 설정
Laravel 라우트 그룹 설정 (articles.new 컴포넌트 생성 및 글 작성 폼 만들기)
Laravel Livewire, 개별글 표시하기 (라우트 모델 바인딩)
위의 코드와 관련된 포스트들이다.
위의 포스트들에서 이미 충분히 설명했으니, 코드에 대한 설명은 생략하겠다.
개별글 페이지에 글 수정 버튼 생성
resources/views/pages/articles/⚡show.blade.php
<div class="border rounded-md p-3">
<!-- 생략 -->
<hr class="my-3">
<p>{{$article->body}}</p>
</div>
<div class="flex items-center justify-end mt-3">
<a href="{{ route('articles.edit', $article) }}" class="inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150" wire:navigate>
{{ __('Edit') }}
</a>
</div>
글 수정 버튼을 만들었다. (정확히는 버튼처럼 생긴 링크다.)
두 div 태그 중에서 위쪽은 원래 있던 코드고, 아래쪽이 글 수정 버튼이다.
버튼을 오른쪽으로 정렬하기 위해서 <div class="flex items-center justify-end mt-3"> 태그로 감쌌다.
개별글 페이지에 글 수정 버튼이 생겼다.
이 캡처 이미지처럼 버튼을 한글화를 하기 위해서는 lang/ko.json 파일에 코드를 추가하면 된다.
Laravel 회원가입 폼 수정: 아이디와 닉네임 필드 추가 및 한글화
그 방법은 이 포스트 혹은 상단의 깃허브 링크를 참고하자.
글 수정 기능 구현 (fill 메서드)
이제 본격적으로 글을 수정하는 기능을 만들 차례다.
resources/views/pages/articles/⚡edit/edit.php
new class extends Component
{
public Article $article;
#[Validate('required|exists:categories,id')]
public int $category_id;
#[Validate('required|string|max:60')]
public string $title;
#[Validate('required|string|max:21844')]
public string $body;
public $childCategories = [];
public function mount(Article $article)
{
$this->article = $article;
$this->fill($this->article->only(['category_id', 'title', 'body']));
$this->childCategories = Category::whereNotNull('parent_id')
->pluck('name', 'id')
->toArray();
}
public function save()
{
$this->validate();
$this->article->update(
$this->only(['category_id', 'title', 'body'])
);
return $this->redirectRoute('articles.show', $this->article, navigate: true);
}
};
새 글 저장 기능을 구현했을 때와 겹치는 코드들이 많다.
이미 설명했던 코드들은 생략하고, 설명한 적이 없는 코드들에 대해서만 설명하겠다.
public int $category_id;: 각 프로퍼티 선언문 앞에 데이터 타입(int,string등)을 명시했다.$this->article = $article;: 라우트 모델 바인딩으로 받아온$article데이터를 클래스의 프로퍼티로 저장한다.$this->fill($this->article->only(['category_id', 'title', 'body']));: 라라벨 Livewire에서$this->fill()메서드는 여러 개의 컴포넌트 프로퍼티(클래스 변수)에 한 번에 값을 대입해 주는 헬퍼 메서드다. 기존$article객체에서 수정에 필요한 3개 데이터만 추출하여 동일한 이름을 가진 컴포넌트의 프로퍼티($this->category_id등)에 한 번에 값을 채워넣는 역할을 한다. 즉, category_id, title, body 등의 필드에 기존 데이터를 미리 입력해준다.$this->article->update( ... );:update()메서드는 데이터베이스에서 해당 글의 데이터를 수정한다. 그 안의$this->only([ ... ])는 아래에 링크한 포스트인 '라라벨 Livewire를 이용해서 새 글 저장 기능 구현'에서 설명했었다.return $this->redirectRoute('articles.show', $this->article, navigate: true);: 글의 수정이 끝나면 해당 글의 개별글 페이지로 리다이렉트 된다.$this->article은 상세 페이지 URL을 생성하는 데 필요한 라우트 파라미터Route Parameter 역할을 한다.
Laravel Livewire, 개별글 표시하기 (라우트 모델 바인딩)
위에서 한번 링크했었던 포스트지만 다시 가져왔다.
public Article $article;에 대한 설명은 여기서 이미 했었다.
라라벨 Livewire로 새 글 작성 시 유효성 검사 기능 구현
그 아래의 #[Validate] 어트리뷰트를 사용해서 유효성 검사를 하는 부분은 이 포스트에서 정리했었다.
라라벨 Livewire를 이용해서 새 글 저장 기능 구현
그 아래의 코드들은 대부분 이 포스트에서 설명했었다.
resources/views/pages/articles/⚡edit/edit.blade.php
<div>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Edit') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-3 lg:px-4">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
<form wire:submit="save" class="space-y-4">
<!-- Category -->
<div>
<x-input-label for="category_id" :value="__('Category')" />
<x-select wire:model="category_id" id="category_id" class="block mt-1 w-full" name="category_id" required>
@foreach ($childCategories as $id => $name)
<option value="{{ $id }}">
{{ $name }}
</option>
@endforeach
</x-select>
<x-input-error :messages="$errors->get('category_id')" class="mt-2" />
</div>
<!-- Title -->
<div>
<x-input-label for="title" :value="__('Title')" />
<x-text-input wire:model="title" id="title" class="block mt-1 w-full" type="text" name="title" required autofocus autocomplete="off" />
<x-input-error :messages="$errors->get('title')" class="mt-2" />
</div>
<!-- Body -->
<div>
<x-input-label for="body" :value="__('Body')" />
<x-textarea wire:model="body" id="body" rows="4" class="block mt-1 w-full" name="body" required autocomplete="off"></x-textarea>
<x-input-error :messages="$errors->get('body')" class="mt-2" />
</div>
<div class="flex items-center justify-end">
<x-primary-button>
{{ __('Save') }}
</x-primary-button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
새 글을 저장할 때의 ⚡new.blade.php코드와 거의 동일하다.
<form wire:submit="save">와 wire:model="..."에 대한 설명도 위에 링크한 포스트인 '라라벨 Livewire를 이용해서 새 글 저장 기능 구현'에서 이미 했었다.
이젠 글을 수정할 수 있게 됐다.
하지만 아직은 완벽하지 않다.
현재는 남의 글도 수정할 수 있다는 치명적인 문제가 남아있다.
이 문제는 글을 삭제하는 기능까지 구현한 후에 해결하도록 하겠다.
다음 포스트

0 Comments
댓글 쓰기
🔸 댓글은 블로그 운영자의 승인 후에 블로그에 표시됩니다.
🔸 비로그인 방문자 분께서는 '익명'보다 이름/URL로 댓글을 남겨주시면 감사하겠습니다. (URL은 생략 가능합니다.)
🔸 구글 로그인 방문자는 '알림 사용'에 체크를 하시면, 남겨주신 댓글에 대한 답글 알림을 메일로 받아볼 수 있습니다. 📩