유효성검사 (FormRequest/Rule)


Request

1. Request객체가 제공하는 validate메서드를 사용한다

// 컨트롤러등에 추가
$validated = $request->validate([
    'title' => 'required|unique:posts|max:255', // 문자열에서 | 로 구분해서 사용
    'body' => ['required','max:255'], // 배열로 구분해서 사용
]);

2. 에러표시

  1. $errors라는 변수가 view에서 항상 정의 되어있고 에러가 나면 해당 변수에 에러내용이 할당된다

<ul>
    @foreach ($errors->all() as $error)
       <li>{{ $error }}</li>
    @endforeach
</ul>
  1. @error지시어

@error(key)으로 에러내용이 담긴 변수 $message를 사용함

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

3. 에러시 이전 입력내용 표시

$title = $request->old('title'); // request인스턴스를 사용하거나
<input type="text" name="title" value="{{ old('title') }}"> // 전역 old헬퍼를 사용함

4.복잡한 유효성 체크를 위해 Form Request 사용

php artisan make:request StorePostRequest // form request 생성



문자열 *

아래의 모든 요소라는 의미

'tags' => [          // 'tags' 배열
   [                 // 'tags' 배열의 첫 번째 요소 ('tags.*')
      'id' => [      // 'tags.*.id' 배열 
         'subid' => 1 // 'tags.*.id.subid' 값
      ]
   ],
   [
      'id' => [      // 'tags' 배열의 두 번째 요소 ('tags.*')
         'subid' => 2 // 'tags.*.id.subid' 값
      ]
   ],
]
// 예제1
$this->validate($request, [ 'tags.*' => 'required|distinct', ]);

// 실제데이터
// 여기서 * 는 tags의 각 요소
[  'tags' => ['Programming', 'AI', 'Machine Learning', 'OpenAI']   ]
// 예제2
$this->validate($request, [
    'tags.*.id' => 'exists:tags,id',
]);

// 실제 데이터
// 여기서 * 는 tags의 각 요소배열
$request->merge([
    'tags' => [
        ['id' => 1],
        ['id' => 2],
        ['id' => 3],
        ['id' => 4]
    ]
]);



FormRequest

- 유효성 포맷

'color'=>['in:green,red'] // 문자가 green,red인 경우만 허용
'upload'=>['file','size:10'] // 파일형태에 사이즈가 10kb
'email'=>['confirmed'] // email_confirmation 필드가 같은값인지 체크
'name'=>'unique:users' // users테이블의 name칼럼에 입력받은 name필드의 값이 중복되는지 확인 
'email' => 'unique:App\Models\User,email_address' 6
'mail' => 'unique:users,email' // users테이블에 email칼럼에 입력받은 mail필드의 값이 중복하는지 확인


- 메세지 추가방법

  1. 메세지 추가방법

public function messages(){
    return [
        'title.required' => '타이틀은 필수입력사항입니다',
    ];
}
  1. 사용자 정의 메세지 추가 (다국어)

app/lang/ko/validation.php

1. 필드명 추가법
'attributes' => [추가할 필드명] 
2. 에러문장 수정
'required' => ':attribute 필드는 필수입니다.'


- 화면에 에러 메세지 표시방법

  • 화면에 항상 $errors변수가 존재한다

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
  • Illuminate\Support\MessageBag의 객체와 view에 표시되는 $errors는 동일 객체이다

// 컨트롤러
$messages = new Illuminate\Support\MessageBag;
$messages->add('error1', '에러메시지1입니다');

return Redirect::back()->withErrors($messages);

?>

<!-- 뷰 파일 -->
@if($errors->has('error1'))
  @foreach($errors->get('error1') as $error)
    <p class="alert alert-danger">{{$error}}</p> <!-- 에러메시지1입니다 -->
  @endforeach
@endif


- 검증된 값 사용하기

['title' => $title, 'content' => $content] = $request->validated();
$validated = $request->safe()->only(['title', 'content']);


- form화면에서 이전에 전송한 입력이전의 값 사용하기

old('category', $post->category) // 이전에 form으로 전송한 category필드 데이터가 있으면 그걸 사용한다. 없으면 입력받은 $post->category을 사용한다

입력받은 내용이 foreach의 option을 통해서 === $category 일치하는 카테고리가 있으면 selected된다

<select name="category" id="category">
    @foreach (['life', 'javascript', 'vuejs', 'php', 'others'] as $category)
        <option value="{{ $category }}"
            {{ old('category', $post->category) === $category ? 'selected' : '' }}>
            {{ strtoupper($category) }}
        </option>
    @endforeach
</select>


- 검증이전과 검증이후에 해당 값에 대해 전처리 후처리하기

해당 메서드를 오버라이딩해서 검증 전후로 값에 대한 처리를 할수있다(나는 패스워드 입력시 hash로 만들어주는 부분에 응용)

passedValidation() // 후처리용
prepareForValidation() // 전처리용


- 폼리퀘스트에서 사용자 정의 유효성처리

  • redirect()->back() // 요청한 페이지로 돌아감

  • $this->input() // 입력한 값

  • withInput() //이전 입력 데이터를 세션에 저장하여 폼 유효성 검사와 관련하여 사용. withInput()로 전달한 내용을 view에서 old()함수등으로 표시함

  • with() // 주로 데이터를 뷰(View)로 전달 , 현재 요청에 대해서만 사용가능하며 다음 요청에서 사용 불가

    결론적으로, withInput()은 주로 리다이렉션 후 이전 입력 데이터를 세션에 저장하여 폼 유효성 검사와 관련하여 사용되고, with()는 데이터를 뷰로 전달하여 뷰에서 사용할 수 있도록 세션에 저장되는 용도

  • withErrors() // with()와 비슷한 용도지만 에러메세지를 보내기 위함이라는 점이 다르다. 첫번째 인수로 Illuminate\Support\MessageBag를 전달한다

  • $validator->errors()는 MessageBag을 반환한다(참조의 링크참조)

protected function failedValidation(Validator $validator)
{
    $response = redirect()->back()
        ->withInput($this->input())
        ->with([
            'error-message' => __("The password is incorrect.")
        ])
        ->withErrors($validator->errors(), $this->errorBag);

    throw new HttpResponseException($response);
}

Rule

사용자 정의 유효성 검사 만들기


php artisan make:rule LanguageValidation // 해당 명령어로 사용자 정의 유효성 검사 객체 생성

위의 명령어를 실행하면 app/Rules 폴더 안에 해당 객체가 생성됨

// 생성된 rule파일
class LanguageValidation implements Rule
{
    public function passes($attribute, $value)
    {
        // false일 경우 message()함수를 통해서 에러를 반환하며
        // true일 경우 통과
        return !($value && session('locale') === 'ko');
    }

    public function message()
    {
        return __(('Translation saving is not possible when the language setting is in Korean.'));
    }
}
// 유효성 검사할 request파일
use App\Rules\LanguageValidation;  // 1. rule을 import한다

class UpdatePostRequest extends FormRequest
{
    public function rules()
    {
        return [
            'translate-active' => ['required', 'boolean', new LanguageValidation], // 2.사용을 위해 new LanguageValidation사용
        ];
    }
}

참조

https://gonpress.tistory.com/35

https://laravel.kr/docs/9.x/validation#%EA%B2%80%EC%A6%9D%EC%9D%84%20%EC%9C%84%ED%95%9C%20%EC%9E%85%EB%A0%A5%20%EC%A4%80%EB%B9%84

https://devdocs.io/laravel~9/api/9.x/illuminate/contracts/validation/validator

Jul 11, 2023 Views 138