Laravel CRUD 초급 예제
- Laravel 9 CRUD 초급 예제 1부 : Setting & Create- Laravel 9 CRUD 초급 예제 2부 : Read & Update & Delete
- Laravel 9 CRUD 예제 3부 : 페이지네이션(Pagination)
- Laravel 9 CRUD 예제 4부 : 유효성 검사(Validation)
라라벨 공부
Step 1. 이전 유효성 검사
이전 포스트에서도 유효성 검사를 넣었지만 이는 추천하지 않는 방법입니다.
왜냐하면 사이트가 커질수록 체크해야 하는 Request와 조건들이 많아질 것인데 그럴 때마다 Controller에 코드가 길어지는 것은 보기 좋지 않기 때문이죠.
...
class ProductController extends Controller
{
...
public function store(Request $request)
{
// 만약 검사해야할 값들과 범위가 훨씬 많아진다면??
$request = $request->validate([
'name' => 'required',
'content' => 'required'
]);
$this->product->create($request);
return redirect()->route('products.index');
}
...
public function update(Request $request, Product $product){
// 만약 검사해야할 값들과 범위가 훨씬 많아진다면??
$request = $request->validate([
'name' => 'required',
'content' => 'required'
]);
$product->update($request);
return redirect()->route('products.index', $product);
}
...
}
그렇기에 위 방법처럼 Controller에서 Request에 유효성 검사를 하는 것이 아닌 Form Request Class를 만들어 처리하는 것을 추천드립니다.
Step 2. Form Requst Class
Form Request Class를 만드는 방법은 간단합니다
아래 명령어를 입력합시다.
php artisan make:request StoreProductRequest
그러면 아래와 같은 경로에 파일이 생성됩니다.
app/Http/Requests/StoreProductRequest.php
그리고 아래의 내용으로 수정해줍시다.
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreProductRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
// 이 값은 현재 유저가 저장이 가능한 지 검사하는 역할입니다만 지금은 유저의 권한 개념이 없으므로 true
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
// ProductController의 조건과 더불어 신규 조건을 추가했습니다
return [
'name' => 'required|max:63',
'content' => 'required|max:255'
];
}
}
ProductController로 또한 아래와 같이 수정해줍시다.
...
use App\Http\Requests\StoreProductRequest;
class ProductController extends Controller
{
...
public function store(StoreProductRequest $request)
{
$validated = $request->validated();
$this->product->create($validated);
return redirect()->route('products.index');
}
...
}
그러면 이전과 똑같이 작동하지만 Controller의 코드는 한결 깔끔해진 걸 볼 수 있습니다.
하지만 우리는 한국사람인데 에러 로그는 영어입니다.
그럴 경우 아래와 같이 유효성 감사 문구 또한 바꿀 수 있습니다.
아래와 같이 app/Http/Requests/StoreProductRequest.php를 수정해줍시다.
...
class StoreProductRequest extends FormRequest
{
...
public function messages()
{
return [
'name.required' => '제목이 비어있습니다.',
'name.max' => '제목은 63자 이하입니다.',
'content.required' => '내용이 비어있습니다.',
'content.max' => '내용은 255자 이하입니다.',
];
}
}
그러면 아래와 같이 에러 문구가 한글로 바뀌었을 것입니다.
Step 3. 이전 입력 값 기억하기
위에 이미지를 보시면 이전에 입력값이 아예 사라져 다시 입력해야 하는 번거로움이 있습니다.
이는 old 헬퍼 함수를 사용하면 됩니다.
resources/views/products/create.blade.php를 아래처럼 수정합시다.
{{-- layout 으로 --}}
@extends('products.layout')
{{-- 아래 html 을 @yield('content') 에 보낸다고 생각하시면 됩니다. --}}
@section('content')
<h2 class="mt-4 mb-3">Product Create</h2>
{{-- 유효성 검사에 걸렸을 경우 --}}
@if ($errors->any())
<div class="alert alert-warning" role="alert">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{route('products.store')}}" method="post">
{{-- old는 전역 헬퍼 함수로 blade 내에서 이전 Request 입력값을 가져와 줍니다. --}}
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" name="name" class="form-control" id="name" autocomplete="off" value="{{old('name')}}">
</div>
<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea rows="10" cols="40" name="content" class="form-control" autocomplete="off">{{old('content')}}</textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
@endsection
그러면 아래와 같이 유효성 검사에 걸리더라도 이전 값을 기억하게 됩니다.
Step 4. 정규식 유효성 검사
유효성 검사는 라라벨에서 지원하는 유효성 검사 규칙을 사용해도 좋지만
하지만 직접 정규식으로 만들어야 하는 경우도 존재합니다.
그렇기에 products에 call 컬럼을 추가하고 전화번호 유효성 검사를 만들고자 합니다.
database/migrations/create_products_table.php 파일을 아래처럼 수정하시고
...
public function up() // php artisan migrate 시 실행되는 함수
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name', 64);
$table->string('content', 256);
$table->string('call', 16)->nullable();
$table->timestamps();
});
}
..
atisan으로 테이블을 재생성하거나
php artisan migrate:refresh
아래 sql을 mysql에서 실행해주시길 바랍니다.
alter table products add `call` varchar(16) null;
또한 call 값을 저장하기 위해 product 모델의 대량 할당 조건을 수정해줍시다.
app/Models/product.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class product extends Model
{
use HasFactory;
// 대량 할당이 가능하도록 하는 것, $guarded 와 같이 쓸 수 없지만
// 둘 중 하나는 사용해야 데이터 추가가 가능합니다, 두 변수를 비교해서 공부하시기를 추천드립니다.
protected $fillable = [
'name', 'content', 'call'
];
}
이제 call의 저장이 가능합니다.
저장 페이지를 수정해줍시다.
resources/views/products/create.blade.php
...
<form action="{{route('products.store')}}" method="post">
{{-- old는 전역 헬퍼 함수로 blade 내에서 이전 Request 입력값을 가져와 줍니다. --}}
@csrf
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" name="name" class="form-control" id="name" autocomplete="off" value="{{old('name')}}">
</div>
<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea rows="10" cols="40" name="content" class="form-control" autocomplete="off" id="content">{{old('content')}}</textarea>
</div>
<div class="mb-3">
<label for="call" class="form-label">Call</label>
<input type="text" name="call" class="form-control" id="call" autocomplete="off" value="{{old('call')}}" maxlength="13">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
@endsection
저장 후 보여줄 페이지도 수정해줍시다.
resources/views/products/view.blade.php
@extends('products.layout')
@section('content')
<h2 class="mt-4 mb-3">Product View: {{$product->name}}</h2>
<p style="text-align: right" class="pt-2">{{$product->created_at}}</p>
<div class="content mt-4 rounded-3 border border-secondary">
<div class="p-3">
{{$product->content}}
</div>
</div>
<div class="content mt-4 rounded-3 border border-secondary">
<div class="p-3">
call : {{$product->call}}
</div>
</div>
@endsection
이제 Reqeust Class를 수정해봅시다
app/Http/Requests/StoreProductRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreProductRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
// 이 값은 현재 유저가 저장이 가능한 지 검사하는 역할입니다만 지금은 유저의 권한 개념이 없으므로 true
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
// 조건식이 늘어날 때 마다 | 을 추가해줍니다.
return [
'name' => 'required|max:63',
'content' => 'required|max:255',
'call' => 'required|regex:/(\d{2,3})-(\d{3,4})-(\d{4})/'
];
}
public function messages()
{
return [
'name.required' => '제목이 비어있습니다.',
'name.max' => '제목은 63자 이하입니다.',
'content.required' => '내용이 비어있습니다.',
'content.max' => '내용은 255자 이하입니다.',
'call.required' => '전화번호가 비어있습니다.',
'call.regex' => '올바른 전화번호 형태가 아닙니다.',
];
}
}
결과물입니다.
4번을 해보시면 아시겠지만
이렇게 라라벨 유효성 검사 클래스를 따로 빼놓는 것으로 Controller의 소스는 건들지 않고
수정이 가능한 것을 볼 수 있습니다.
또한 따로 빼놓으니 가독성도 훨씬 좋습니다.
'PHP > Laravel' 카테고리의 다른 글
Laravel9 라라벨 액셀 다운로드 (Laravel-Excel) (0) | 2022.08.19 |
---|---|
Laravel9 라라벨 액셀 다운로드 (Fast-Excel) (0) | 2022.08.19 |
Laravel 9 CRUD 예제 3부 : 페이지네이션(Pagination) (0) | 2022.08.10 |
Laravel 9 CRUD 초급 예제 2부 : Read & Update & Delete (0) | 2022.08.10 |
Laravel 9 CRUD 초급 예제 1부 : Setting & Create (19) | 2022.08.09 |