Validation-유효성검사

시작하기

라라벨은 어플리케이션에 유입되는 데이터의 유효성을 검사하기 위한 다양한 방법을 제공합니다. 기본적으로, 라라벨의 베이스 컨트롤러 클래스는 다양하고 강력한 유효성 검사 규칙을 적용하여 편리하게 HTTP 요청을 승인하는 메소드를 제공하는 ValidatesRequests 트레이트-trait을 사용하고 있습니다.

Validation 퀵스타트

라라벨의 강력한 유효성 검사 기능에 대해 알아보기 위해서, form을 확인한 뒤 사용자에게 에러 메세지를 보여주는 예제를 살펴보도록 하겠습니다.

라우트 정의하기

우선 다음의 라우트들이 routes/web.php 파일에 정의되어 있다고 가정해 보겠습니다:

Route::get('post/create', 'PostController@create');

Route::post('post', 'PostController@store');

GET 라우트는 사용자가 새로운 블로그 포스트를 생성하기 위한 form을 나타낼 것이고, POST 라우트는 데이터베이스에 새로운 블로그 포스트를 저장할 것입니다.

컨트롤러 생성하기

다음으로, 이 라우트들을 다루는 간단한 컨트롤러를 살펴보겠습니다. 지금은 store 메소드를 비어있는 채로 둘 것입니다:

<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    /**
     * Show the form to create a new blog post.
     *
     * @return Response
     */
    public function create()
    {
        return view('post.create');
    }

    /**
     * Store a new blog post.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate and store the blog post...
    }
}

유효성 검사 로직 작성하기

이제 새로운 블로그 포스트에 대해 유효성을 검사하는 로직을 store 메소드에 채워넣을 준비가 되었습니다. 어플리케이션의 베이스 컨트롤러(App\Http\Controllers\Controller) 클래스를 살펴보면 클래스가 ValidatesRequests 트레이트-trait을 사용한다는 것을 알 수 있습니다. 이 트레이트-trait은 모든 컨트롤러에 편리하게 사용할 수 있는 validate 메소드를 제공합니다.

validate 메소드는 HTTP 요청의 유입과 유효성 검사 룰의 집합을 전달 받습니다. 유효성 검사 룰들을 통과하게되면 코드는 계속해서 정상적으로 실행될 것입니다. 하지만 유효성 검사를 통과하지 못할 경우, 예외-exception가 던져지고 적절한 오류 응답이 사용자에게 자동으로 보내질 것입니다. 전통적인 HTTP 요청의 경우, 리다이렉트 응답이 생성될 것이며 AJAX 요청에는 JSON 응답이 보내질 것입니다.

validate 메소드에 대해 더 잘 이해하기 위해, 다시 store 메소드로 돌아가 보겠습니다:

/**
 * Store a new blog post.
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request)
{
    $this->validate($request, [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // The blog post is valid, store in database...
}

위에서 볼 수 있듯이, 간단하게 유입되는 HTTP 요청과 유효성 검사 룰들을 validate 메소드로 전달하면 됩니다. 이 때에도 유효 확인이 실패하면 적절한 응답이 생성될 것입니다. 유효성 검사를 통과하면 컨트롤러는 계속해서 정상적으로 수행합니다.

첫번째 유효성 검사가 실패하면 중지하기

경우에 따라서 첫번째 유효성 감사가 실패하면 속성값에 대한 검사를 중단하기를 원할수도 있습니다. 이러한 경우 bail 규칙을 지정하면 됩니다:

$this->validate($request, [
    'title' => 'bail|unique:posts|max:255',
    'body' => 'required',
]);

이 예제에서는, unique 규칙으로 지정된 title 속성의 유효성 검사가 실패하면 max 규칙은 확인하지 않습니다. 유효성 검사 규칙은 선언된 순서대로 검사될 것입니다.

중첩된 속성에 대한 유의사항

HTTP 요청이 "중첩된" 파라미터를 가지고 있다면 ".(점)" 문법을 사용하여 유효성 확인 규칙을 지정할 수 있습니다:

$this->validate($request, [
    'title' => 'required|unique:posts|max:255',
    'author.name' => 'required',
    'author.description' => 'required',
]);

유효성 검사 에러를 보여주기

그럼 입력되는 요청-request의 파라미터들이 유효성 검사를 통과하지 못하는 경우에는 어떻게 될까요? 이 경우 라라벨은 앞서 언급한대로, 사용자를 자동으로 이전의 위치로 리다이렉트합니다. 또한 모든 유효성 확인 에러는 자동으로 세션에 임시 저장될 것입니다.

이번에도 GET 라우트에서 에러 메세지를 뷰와 명시적으로 연결하지 않아도 됩니다. 왜냐하면, 라라벨이 세션 데이터에서 에러가 있는지 확인하고, 에러가 있다면 뷰에 자동으로 연결해 주기 때문입니다. 따라서 여러분은 $errors 변수가 항상 정의되어 있으며 사용 가능하다고 마음 편하게 가정할 수 있습니다. $errors 변수는 Illuminate\Support\MessageBag의 인스턴스일 것입니다. 이 객체를 다루는 법에 대해 더 알아보고 싶다면 문서을 확인해보시기 바랍니다.

{tip} $errors 변수는 web 미들웨어 그룹에 의해서 제공되는 Illuminate\View\Middleware\ShareErrorsFromSession 미들웨어에 의해서 뷰와 연결됩니다. 이 미들웨어가 지정되었을 때 $errors 변수는 뷰 안에서 항상 사용가능 할 것이므로, 편하게 생각하면 $errors 변수는 항상 선언되어 있다고 생각하고 안정하게 사용할 수 있습니다.

따라서, 이 예제에서, 유효성 검사를 통과하지 못할 경우 사용자는 컨트롤러의 create 메소드로 리다이렉트 될것이고, 뷰에서는 에러 메세지가 표시됩니다:

<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- Create Post Form -->

옵션 필드에 대한 주의사항

기본적으로 라라벨은 어플리케이션의 글로벌 미들웨어 스택에 TrimStrings 그리고 ConvertEmptyStringsToNull 미들웨어를 포함하고 있습니다. 이 미들웨어는 App\Http\Kernel 클래스의 미들웨어 스택에 나열되어 있습니다. 이때문에, 유효성 검사에서 null이 유효하지 않은것으로 간주하지 않으려면 "선택적-optional" request-요청 필드를 nullable로 표시할 필요도 있습니다. 예를들면:

$this->validate($request, [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
    'publish_at' => 'nullable|date',
]);

이 예제에서는 publish_at 필드가 null이거나 유효한 날짜 형식이라고 지정했습니다. 만약 nullable 규칙이 추가되지 않은 경우 null값은 유효하지 않다고 결정됩니다.

임시저장된 에러의 포맷을 임의로 지정하기

만약 유효성 검사가 실패했을 때 세션에 저장되는 에러의 형식을 커스터마이징하고 싶다면, 베이스 컨트롤러 클래스의 formatErrors 메소드를 오버라이딩하면 됩니다. 이때, 파일 상단에서 Illuminate\Validation\Validator를 임포트하는 것을 잊지 마십시오:

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;

abstract class Controller extends BaseController
{
    use DispatchesJobs, ValidatesRequests;

    /**
     * {@inheritdoc}
     */
    protected function formatValidationErrors(Validator $validator)
    {
        return $validator->errors()->all();
    }
}

AJAX 요청과 유효성 검사

이 예제에서는, 어플리케이션에 전통적인 form을 이용하여 데이터를 보냈습니다. 하지만 많은 어플리케이션이 AJAX 요청을 사용합니다. AJAX reqeust 중에서 validate 메소드를 사용한다면 라라벨은 리다이렉트 응답을 생성하지 않을 것입니다. 대신 라라벨은 유효성 검사의 모든 실패 에러들을 포함하는 JSON 응답을 생성할 것입니다. 이 JSON 응답은 422 HTTP 상태 코드와 함께 보내질 것입니다.

Form Request 유효성 검사

Form Requests 생성하기

보다 복잡한 유효성 검사 시나리오의 경우, "form request"를 작성하는 것이 좋습니다. Form request는 request 클래스의 사용자 정의(커스텀) 클래스로, 유효성 검사 로직을 가지고 있습니다. form request 클래스를 생성하기 위해서는 make:request 아티즌 CLI 명령어를 사용하십시오:

php artisan make:request StoreBlogPost

생성된 클래스는 app/Http/Requests 디렉토리에 저장됩니다. 이 디렉토리가 존재하지 않는다면 make:request 명령어가 실행될 때 생성됩니다. rules 메소드에 몇가지 유효성 검사 규칙을 추가해 보겠습니다:

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

그렇다면 유효성 검사 규칙은 어떻게 실행할까요? 여러분이 해야할일은 컨트롤러 메소드에 request 를 타입-힌트 하는 것입니다. 유입된 form request 는 컨트롤러 메소드가 호출되기 전에 유효성 검사를 수행합니다. 즉 컨트롤러에 유효성 검사 로직을 포함시키지 않아도 됩니다.

/**
 * Store the incoming blog post.
 *
 * @param  StoreBlogPost  $request
 * @return Response
 */
public function store(StoreBlogPost $request)
{
    // The incoming request is valid...
}

유효성 검사가 실패하면 리다이렉션 응답-response이 생성되어 사용자를 이전 위치로 되돌려 보냅니다. 오류를 세션에 임시저장하여 화면에 표시 할 수도 있습니다. AJAX 요청인 경우 유효성 검사 오류가 JSON 형식으로 재구성되어 422 상태 코드가있는 HTTP 응답이 사용자에게 반환됩니다.

Form Request 에 After 후킹 추가하기

form request 에 "after" 후킹을 추가하려면, withValidator 메소드를 사용하면 됩니다. 이 메소드는 생성된 완전한 validator를 전달 받는데, 유효성 검사 규칙이 실제로 수행되기 전에 메소드 중 하나를 호출할 수 있도록 해줍니다:

/**
 * Configure the validator instance.
 *
 * @param  \Illuminate\Validation\Validator  $validator
 * @return void
 */
public function withValidator($validator)
{
    $validator->after(function ($validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}

Form Requests 사용자 승인

form request 클래스는 또한 authorize 메소드를 가지고 있습니다. 이 메소드 안에서 여러분은 인증된 사용자가 주어진 리소스에 대해서 수정할 수 있는 권한이 있는지 확인할 수 있습니다. 예를 들어, 사용자가 블로그 포스트의 탯글을 수정하려고 시도할 때, 그 본인의 코멘트인지 확인할 수 있습니다:

/**
 * Determine if the user is authorized to make this request.
 *
 * @return bool
 */
public function authorize()
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}

모든 form request는 라라벨의 베이스 request 클래스를 확장하고 있기 때문에, 현재 인증된 사용자에 엑세스 하기 위해서 user 메소드를 사용할 수 있습니다. 다음 예제에서 route 메소드를 호출하는것에 주목하십시오. 예제에서 이 메소드는 {comment} 파라미터와 같이 파라미터가 정의된 라우트의 URI 에 여러분이 엑세스 접근할 수 있는지 권한을 확인합니다:

Route::post('comment/{comment}');

만약 authorize 메소드가 false를 리턴하면, 403 HTTP 응답이 자동적으로 반환되고 컨트롤러 메소드는 실행되지 않을 것입니다.

여러분이 어플리케이션의 다른 부분에 있는 인증로직을 사용할 계획이라면, 그냥 authorize 메소드에서 true를 리턴하면 됩니다.

/**
 * Determine if the user is authorized to make this request.
 *
 * @return bool
 */
public function authorize()
{
    return true;
}

에러의 포맷을 임의로 지정하기

만약 유효성 검사가 실패했을 때 세션에 저장되는 에러의 형식을 커스터마이징하고 싶다면, 베이스 request-요청 클래스(App\Http\Requests\Request)의 formatErrors 메소드를 오버라이딩하면 됩니다. 이때, 파일 상단에서 Illuminate\Validation\Validator를 임포트하는 것을 잊지 마십시오:

/**
 * {@inheritdoc}
 */
protected function formatErrors(Validator $validator)
{
    return $validator->errors()->all();
}

에러 메세지를 사용자 정의하기(커스터마이징하기)

messages 메소드를 대체하면 form request-요청이 사용하는 에러 메세지를 커스터마이즈할 수 있습니다. 이 메소드는 속성 / 규칙의 쌍으로된 배열과 그에 상응하는 오류 메세지를 반환합니다:

/**
 * Get the error messages for the defined validation rules.
 *
 * @return array
 */
public function messages()
{
    return [
        'title.required' => 'A title is required',
        'body.required'  => 'A message is required',
    ];
}

수동으로 Validator 생성하기

ValidatesRequests 트레이트-trait의 validate 메소드를 사용하고 싶지 않다면 Validator 파사드를 사용하여 validator 인스턴스를 수동으로 생성할 수 있습니다. 파사드에 make 메소드를 사용하면 새로운 validator 인스턴스가 생성됩니다:

<?php

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * Store a new blog post.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
            return redirect('post/create')
                        ->withErrors($validator)
                        ->withInput();
        }

        // Store the blog post...
    }
}

make 메소드로 전달되는 첫번째 인자는 유효성 검사를 받을 데이터입니다. 두번째 인자는 데이터에 적용되어야 하는 유효성 검사 규칙들입니다.

request-요청이 유효성 검사에 실패하였는지 확인한 후에 withErrors 메소드로 세션에 에러 메세지를 임시저장-flash 할 수 있습니다. 이 메소드를 사용하면 리다이렉트 후에 $errors 변수가 자동으로 뷰에서 공유되어 손쉽게 사용자에게 보여질 수 있습니다. withErrors 메소드는 validator, MessageBag, 혹은 PHP array를 전달 받습니다.

자동으로 리다이렉트하기

수동으로 validator 인스턴스를 생성하더라도, ValidatesRequest 트레이트에 의해서 자동으로 리다이렉트 되는 이점을 유지하고 싶다면, validator 인스턴스에 validate 메소드를 호출하면 됩니다. 유효성 검사가 실패하는 경우, 사용자는 자동으로 리다이렉트 되거나, 또는 AJAX 요청인 경우, JSON이 반환됩니다:

Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();

이름이 지정된 Error Bags

한 페이지 안에서 여러개의 form을 가지고 있다면 에러들의 MessageBag에 이름을 붙여 지정한 form에 맞는 에러 메세지를 조회할 수 있도록 할 수 있습니다. 단순히 withErrors에 이름을 두번째 인자로 전달하면 됩니다:

return redirect('register')
            ->withErrors($validator, 'login');

그러면 $errors 변수에서 지정된 MessageBag 인스턴스에 접근할 수 있습니다:

{{ $errors->login->first('email') }}

유효성 검사 이후에 후킹하기

유효성 검사가 완료된 후에 실행하고자 하는 콜백함수를 validator에 추가할 수 있습니다. 이를 통하면, 손쉽게 더 많은 유효성 검사를 실행할 수 있도록 하고, 에러 메시지 컬렉션에 에러 메시지를 더 추가할 수도 있습니다. 다음처럼 validator 인스턴스의 after 메소드를 사용하면 됩니다:

$validator = Validator::make(...);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add('field', 'Something is wrong with this field!');
    }
});

if ($validator->fails()) {
    //
}

에러 메시지 사용하기

Validator 인스턴스의 messages 메소드를 호출하면, 에러 메시지를 편하게 사용할 수 있는 다양한 메소드를 가진 MessageBag 인스턴스를 받을 수 있습니다. $errors 변수는 자동으로 모든 뷰에서 MessageBag 클래스 인스턴스로써 사용가능합니다.

하나의 필드에 대한 첫번째 에러 메시지 조회하기

특정 필드에 대한 첫번째 에러 메세지를 조회하려면 first 메소드를 사용하면 됩니다:

$errors = $validator->errors();

echo $errors->first('email');

하나의 필드에 대한 모든 에러 메세지 조회하기

특정 필드에 대한 모든 메세지에 대한 배열을 조회하고자 한다면, get 메소드를 사용하면 됩니다:

foreach ($errors->get('email') as $message) {
    //
}

배열형태의 form 필드에 대해서 유효성 검사를 하려면, 배열의 각각의 요소는 * 문자열을 사용하여 모든 메세지를 조회할 수 있습니다:

foreach ($errors->get('attachments.*') as $message) {
    //
}

모든 필드에 대한 모든 에러 메세지 조회하기

모든 필드에 대한 모든 에러 메세지를 조회하기 위해서는 all 메소들 사용하면 됩니다:

foreach ($errors->all() as $message) {
    //
}

하나의 필드에 대하여 에러 메시지가 존재하는지 검사하기

has 메소드는 특정 필드에 대한 에러 메세지가 존재하는지 확인하는데 사용합니다:

if ($errors->has('email')) {
    //
}

사용자 지정(커스텀) 에러 메세지

필요하다면 기본적인 에러 메세지 대신에 커스텀 에러 메세지를 유효성 검사에 사용할 수 있습니다. 커스텀 메세지를 지정하는 데에는 여러가지 방법이 있습니다. 먼저 Validator::make 메소드에 커스텀 메세지를 세번째 인자로 전달할 수 있습니다:

$messages = [
    'required' => 'The :attribute field is required.',
];

$validator = Validator::make($input, $rules, $messages);

다음의 예에서 :attribute 플레이스 홀더는 유효성 검사를 받는 필드의 실제 이름으로 대체됩니다. 유효성 검사 메세지에서 다른 플레이스 홀더들 또한 활용할 수 있습니다. 예를 들어:

$messages = [
    'same'    => 'The :attribute and :other must match.',
    'size'    => 'The :attribute must be exactly :size.',
    'between' => 'The :attribute must be between :min - :max.',
    'in'      => 'The :attribute must be one of the following types: :values',
];

주어진 속성에 대해 커스텀 메세지 지정하기

종종 하나의 특정 필드에 대해서만 커스텀 오류 메세지를 지정해야 하는 경우가 있습니다. 이것은 ".(점)" 표기법을 통해서 할 수 있습니다. 속성의 이름을 먼저 지정하고, 규칙을 명시하면됩니다:

$messages = [
    'email.required' => 'We need to know your e-mail address!',
];

언어 파일에 커스텀 메세지 지정하기

대부분의 경우에서, Validator에 직접 메세지를 전달하는 대신, 언어 파일의 커스텀 메세지를 지정하기 원할 수 있습니다. 이렇게 하기 위해서는 resources/lang/xx/validation.php 언어 파일의 custom 배열에 메제지를 추가하면 됩니다.

'custom' => [
    'email' => [
        'required' => 'We need to know your e-mail address!',
    ],
],

언어파일에 커스텀 속성 지정하기

유효성 검사 메세지의 :attribute 부분을 사용자 정의 속성 이름으로 교체하려면 resources/lang/xx/validation.php언어 파일의 attributes 배열에 사용자 정의 이름을 지정하면 됩니다:

'attributes' => [
    'email' => 'email address',
],

사용가능한 유효성 검사 규칙

다음은 사용 가능한 모든 유효성 검사 규칙과 그 기능의 목록입니다:

accepted

필드의 값이 yes, on, 1, 또는 _true_이어야 합니다. 이 것은 "이용약관" 동의와 같은 필드의 검사에 유용합니다.

active_url

필드의 값이 PHP 함수 dns_get_record에서 확인 가능한 올바른 A 또는 AAAA 레코드여야 합니다.

after:date

필드의 값이 주어진 날짜 이후여야 합니다. 이때 날짜는 strtotime PHP 함수를 통해 생성된 값입니다.

'start_date' => 'required|date|after:tomorrow'

strtotime에 의해 계산될 날짜 문자열을 전달하는 대신 날짜와 비교할 다른 필드를 명시할 수 있습니다:

'finish_date' => 'required|date|after:start_date'

after_or_equal:date

필드의 값이 주어진 날짜와 동일하거나, 이후여야 합니다. 보다 자세한 사항은 after 규칙을 확인하십시오.

alpha

필드의 값이 완벽하게 (숫자나 기호가 아닌) 알파벳[자음과 모음] 문자로 이루어져야 합니다.

(역자주: 영문 알파벳만을 의미하지 않고, 숫자나 기호가 아닌경우에 해당하여, 한글도 허용합니다.)

alpha_dash

필드의 값이 (숫자나 기호가 아닌) 알파벳[자음과 모음] 문자 및 숫자와 dash(-), underscore(_)로 이루어져야 합니다.

alpha_num

필드의 값이 완벽하게 (숫자나 기호가 아닌) 알파벳[자음과 모음] 문자 및 숫자로 이루어져야 합니다.

array

필드의 값이 반드시 PHP 배열 형태이어야 합니다.

before:date

필드의 값이 반드시 주어진 날짜보다 앞서야 합니다. 날짜는 strtotime PHP 함수를 통해 비교됩니다.

before_or_equal:date

필드의 값이 주어진 날짜보다 앞서거나, 같아야 합니다. 날짜는 strtotime PHP 함수를 통해서 비교됩니다.

between:min,max

필드의 값이, 주어진 min 과 _max_의 사이의 값이어야 합니다. 문자열, 숫자, 배열 그리고 파일이 size 룰에 의해 같은 방식으로 계산될 수 있습니다.

boolean

필드의 값이 반드시 boolean으로 캐스팅될 수 있어야 합니다. 허용되는 값은 true, false, 1, 0, "1", "0" 입니다.

confirmed

필드의 값이 foo_confirmation의 매칭되는 필드를 가져야 합니다. 예를 들어 만약 필드가 password라면, password_confirmation라는 필드가 입력값 중에 있어야 합니다.

date

필드의 값이 strtotime PHP 함수에서 인식할 수 있는 올바른 날짜여야 합니다.

date_format:format

필드의 값이 반드시 주어진 _format_과 일지해야 합니다. 필드의 유효성을 검사할 때에는 datedate_format하나만 사용해야 합니다.

different:field

필드의 값이 주어진 _field_의 값과 달라야 합니다.

digits:value

필드의 값이 반드시 _숫자_여야 하고, 길이가 _value_이어야 합니다.

digits_between:min,max

필드의 값이 주어진 _min_과 max 사이의 길이를 가져야 합니다.

dimensions

필드의 값이 룰에 지정된 파라미터들을 만족하는 이미지이어야 합니다.

'avatar' => 'dimensions:min_width=100,min_height=200'

사용가능한 제약은: min_width, max_width, min_height, max_height, width, height, ratio 입니다.

ratio 제약은 가로를 세로로 나눈 비율을 표현해야합니다. 이는 3/2 또는 소수점 1.5 처럼 지정될 수 있습니다:

'avatar' => 'dimensions:ratio=3/2'

이 룰은 여러개의 인자를 필요로 하는데, 다음처럼 Rule:dimensions 메소드를 사용하여 유연하게 룰을 생성할 수 있습니다:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'avatar' => [
        'required',
        Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
    ],
]);

distinct

배열에서 동작하며, 필드의 값이 배열안의 다른 값과 중복되지 않아야 합니다.

'foo.*.id' => 'distinct'

email

필드의 값이 이메일 주소 형식이어야 합니다.

exists:table,column

필드의 값이 주어진 데이터베이스 테이블에 존재하는 값이어야 합니다.

exists 룰의 기본 사용법

'state' => 'exists:states'

특정 컬럼명 지정하기

'state' => 'exists:states,abbreviation'

때때로, exists 쿼리에서 사용할 데이터베이스 커넥션을 지정하고자 할 수도 있습니다. 이경우 커넥션의 이름을 테이블 이름 앞에 "점" 문법을 사용하여 표기할 수도 있습니다.

'email' => 'exists:connection.staff,email'

유효성 검사 규칙에 의해서 실행되는 쿼리를 커스터마이징 하고자 한다면, 규칙에 Rule 클래스를 정의해서 사용할 수 있습니다. 다음 예제에서 | 문자를 구분자로 사용하는 대신에 유효성 검사 규칙을 배열로 지정하고 있습니다:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function ($query) {
            $query->where('account_id', 1);
        }),
    ],
]);

file

필드의 값이 완전히 업로드된 파일이어야 합니다.

filled

필드가 존재하는 경우 값이 비어있으면 안됩니다.

image

이미지 파일(jpeg, png, bmp, gif, svg)이어야 합니다.

in:foo,bar,...

필드의 값이 주어진 목록에 포함돼 있어야 합니다. 이 룰은 자주 배열을 implode 하는 것을 필요로 하며, 다음처럼 Rule:in 메소드를 사용하여 편리하게 생성할 수 있습니다:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'zones' => [
        'required',
        Rule::in(['first-zone', 'second-zone']),
    ],
]);

in_array:anotherfield

필드의 값이 주어진 다른 필드의 값안에 존재해야만 합니다.

integer

필드의 값이 정수여야 합니다.

ip

필드의 값이 IP 주소여야 합니다.

ipv4

필드의 값이 IPv4 주소여야 합니다.

ipv6

필드의 값이 IPv6 주소여야 합니다.

json

필드의 값이 유효한 JSON 문자열이어야 합니다.

max:value

필드의 값이 반드시 _value_보다 작거나 같아야 합니다. 문자열, 숫자, 배열, 그리고 파일이 size 룰에 의해 같은 방식으로 평가될 수 있습니다.

mimetypes:text/plain,...

파일이 주어진 MIME 타입들 중 하나와 일치해야만 합니다.

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

업로드 파일의 MIME 타입을 지정하고자 한다면, 프레임 워크는 파일의 내용을 읽어 들여 MIME 타입을 추측하게 되며 클라이언트가 제공하는 MIME 타입과 달라질 수 있습니다.

mimes:foo,bar,...

파일의 MIME 타입이 주어진 확장자 리스트 중에 하나와 일치해야 합니다.

MIME 룰의 기본 사용법

'photo' => 'mimes:jpeg,bmp,png'

여러분은 확장자를 지정하기만 하면 되지만, 이 경우 파일의 컨텐트를 읽고 MIME 타입을 추정함으로써 이 파일의 MIME의 유효성을 검사합니다.

MIME 타입과 그에 상응하는 확장의 전체 목록은 다음의 위치에서 확인하실 수 있습니다: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

min:value

필드의 값이 반드시 value 보다 크거나 같아야 합니다. 문자열, 숫자, 배열, 그리고 파일이 size 룰에 의해 같은 방식으로 평가될 수 있습니다.

nullable

필드의 값은 null 일 수 있습니다. 이는 특히 null 을 포함한 문자열이나 정수형과 같은 기본 타입에 대해서 유효성검사를 할 때 유용합니다.

not_in:foo,bar,...

필드의 값이 주어진 목록에 존재하지 않아야 합니다. Rule::notIn 메소드는 검사룰을 보다 유연하게 구성하는데 사용할 수 있습니다:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'toppings' => [
        'required',
        Rule::notIn(['sprinkles', 'cherries']),
    ],
]);

numeric

필드의 값이 숫자여야 합니다.

present

필드가 존재하고 있는지 확인하지만, 값이 비어있을 수 있습니다.

regex:pattern

필드의 값이 주어진 정규식 표현과 일치해야 합니다.

참고: regex 패턴을 사용할 때, 특히 정규 표현식에 파이프 문자열이 있다면, 파이프 구분자를 사용하는 대신 배열 형식을 사용하여 룰을 지정할 필요가 있습니다.

required

입력 값 중에 해당 필드가 존재해야 하며 비어 있어서는 안됩니다. 필드는 다음의 조건 중 하나를 충족하면 "빈(empty)" 것으로 간주됩니다:

  • 값이 null인 경우.
  • 값이 비어있는 문자열인 경우.
  • 값이 비어있는 배열이거나, 비어있는 Countable 객체인경우
  • 값이 경로없이 업로드된 파일인 경우

required_if:anotherfield,value,...

만약 _anotherfield_의 값이 _value_중의 하나와 일치한다면, 해당 필드는 존재하고 비어있지 않아야 합니다.

required_unless:anotherfield,value,...

_anotherfield_가 어떤 _value_와도 값이 일치하지 않다면 해당 필드는 존재하고 비어있지 않아야 합니다.

required_with:foo,bar,...

지정된 다른 필드중 하나라도 존재한다면, 해당 필드가 반드시 존재하고 비어있지 않아야 합니다.

required_with_all:foo,bar,...

지정된 다른 필드가 모두 존재한다면, 해당 필드가 반드시 존재하고 비어있지 않아야 합니다.

required_without:foo,bar,...

지정된 다른 필드중 하나라도 존재하지 않으면, 해당 필드가 반드시 존재하고 비어있지 않아야 합니다.

required_without_all:foo,bar,...

지정된 다른 필드들이 모두 존재하지 않으면, 해당 필드가 존재하고 비어있지 않아야 합니다.

same:field

필드의 값이 주어진 _field_의 값과 일치해야 합니다.

size:value

필드의 값이 주어진 _value_와 일치하는 크기를 가져야 합니다. 문자열 데이터에서는 문자의 개수가 _value_와 일치해야 합니다. 숫자형식의 데이터에서는 주어진 정수값이 _value_와 일치해야 합니다. 배열에서는 배열의 count 와 일치해야 합니다. 파일에서는 킬로바이트 형식의 파일 사이즈가 _size_와 일치해야 합니다.

string

필드의 값이 반드시 문자열이어야 합니다. 필드가 null 인것을 허용하려면 규칙에 nullable 을 할당해야만 합니다.

timezone

필드의 값이 timezone_identifiers_list PHP 함수에서 인식 가능한 유효한 timezone 식별자여야 합니다.

unique:table,column,except,idColumn

필드의 값이 주어진 데이터베이스 테이블에서 고유한 값이어야 합니다. 만약 column이 지정돼 있지 않다면 필드의 이름이 사용됩니다.

특정 컬럼명 지정하기:

'email' => 'unique:users,email_address'

특정 데이터베이스 커넥션

때때로, 여러분은 Validator에 의해서 생성되는 데이터베이스 쿼리에 사용자가 지정한 커넥션을 필요로 할지도 모릅니다. 위에서의 검증 규칙 unique:users 에서는 데이터베이스를 쿼리하기 위해 기본 데이터 베이스 커넥션이 사용됩니다. 이를 오버라이드 하려면 테이블 이름 후에 "." 표기법으로 커넥션을 지정하십시오:

'email' => 'unique:connection.users,email_address'

주어진 ID에 대해서 유니크 규칙을 무시하도록 강제하기:

때때로 유니크 검사를 할 때 특정 ID를 무시하고자 할 수 있습니다. 예를 들어 사용자 이름, 이메일 주소 그리고 위치를 포함하는 "프로필 업데이트" 화면이 있습니다. 물론 이메일 주소가 고유하다는 것을 확인하고 싶을 것입니다. 하지만 사용자가 이름 필드만 바꾸고 이베일 필드를 바꾸지 않는다면 사용자가 이미 이메일 주소의 주인이기 때문에 유효 검사 오류가 던져지지 않아야 합니다.

사용자 ID를 무시하도록 지시하려면, 규칙을 유연하게 정의할 수 있는 Rule 클래스를 사용하면 됩니다. 다음 예제에서 규칙을 | 문자를 구분자로 사용하는 대신에 유효성 검사 규칙을 배열로 지정하고 있습니다:

use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

테이블이 id가 아닌 primary 키 컬럼 이름을 사용한다면, ignore 메소드를 호출할 때 컬럼의 이름을 지정하면 됩니다:

'email' => Rule::unique('users')->ignore($user->id, 'user_id')

추가적인 Where 구문 추가하기:

where 메소드를 사용하여 쿼리를 커스터마이징하는 추가 제약을 지정할 수 있습니다. 예를 들어, account_id1인지 확인하는 제약 조건을 추가해 보겠습니다:

'email' => Rule::unique('users')->where(function ($query) {
    $query->where('account_id', 1);
})

url

필드는 반드시 유효한 URL이어야 합니다.

조건부로 룰 추가하기

현재 값이 존재할때 유효성 검사하기

어떤 상황에서는 필드가 입력 배열에 존재할 때에만 그 필드의 유효성 검사를 실행하고 싶을수도 있습니다. 이를 위해서는 룰의 목록에 sometimes를 추가하기만 하면 됩니다:

$v = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

이 예제에서는 $data 배열에 email 필드가 존재할 경우에만 그 필드의 유효성 검사가 실행됩니다.

{tip} 필드가 항상 존재하고 비어있지 않은지 확인하고자 한다면, 선택적 필드 부분을 참고하십시오.

복잡한 조건부 유효성 검사

때때로 여러분은 한가지 이상의 복잡한 로직에 대해서 유효성 규칙을 추가하고자 할 수도 있습니다. 예를 들어, 어떤 다른 필드가 100 이상의 값을 가질때에만 주어진 필드가 반드시 존재하길 바랄 수도 있습니다. 또는 다른 필드가 존재할 때에만 두개의 필드가 주어진 값을 가질 필요가 있을수도 있습니다. 이러한 유효성 검사 룰을 추가하는 것이 어렵지 않을 수 있습니다. 우선 고정 룰 을 변경할 필요 없이 그대로 사용하여 Validator 인스턴스를 생성합니다:

$v = Validator::make($data, [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

여러분의 웹 어플리케이션이 게임 수집가들을 위한 사이트라고 가정해보겠습니다. 만약 100개 이상의 게임을 소유하고 있는 게임 수집가가 우리 사이트에 가입을 한다면, 우리는 그들이 왜 그렇게 많은 게임을 소유하고 있는지 설명을 듣고 싶을수 있습니다. 예를 들어, 아마 그들이 중고게임 판매점을 운영하거나, 단순히 수집을 취미로 할 수도 있습니다. 이런 요구사항을 조건부로 추가하기 위하여 Validator 인스턴스의 sometimes 메소드를 사용할 수 있습니다.

$v->sometimes('reason', 'required|max:500', function ($input) {
    return $input->games >= 100;
});

sometimes 메소드에 전달되는 첫번째 인자는 필드의 이름입니다. 두번째 인자는 추가하려는 룰입니다. 만약 세번째 파라메터로 전달된 Closuretrue를 리턴한다면 그 룰은 유효성 검사에 추가될 것입니다. 이 메소드는 복잡한 조건부 유효성 검사의 구성을 손쉽게 만들어 주며, 한번에 여러개의 필드에 대한 조건부 유효성 검사를 추가할 수도 있습니다.

$v->sometimes(['reason', 'cost'], 'required', function ($input) {
    return $input->games >= 100;
});

{tip} Closure로 전달된 $input 파라메터는 Illuminate\Support\Fluent의 인스턴스입니다. 그리고 입력된 데이터와 파일에 접근하기 위해 이 오브젝트가 사용할 수 있습니다.

배열값 유효성 검사

form 입력필드의 배열을 유효성 검사하는 것을 어렵게 할 필요 없습니다. "점 표기법"을 사용하여 배열안에 있는 유효성 속성을 지정할 수 있습니다. 예를 들어 HTTP request가 가지고 있는 photos[profile] 필드에 대해서 다음과 같이 검사할 수 있습니다:

$validator = Validator::make($request->all(), [
    'photos.profile' => 'required|image',
]);

또한 배열의 각각의 요소들을 검사할 수 있습니다. 예들 들어 주어진 배열 입력값이 각각의 유니크한 이메일인지 확인하려면 다음과 같이 하면 됩니다:

$validator = Validator::make($request->all(), [
    'person.*.email' => 'email|unique:users',
    'person.*.first_name' => 'required_with:person.*.last_name',
]);

마찬가지로, 여러분은 배열을 기반으로한 단일 유효성 검사 메세지 를 사용하는데* 문자를 여러분의 언어파일에 들어 있는 유효성 검사 메세지를 지정할 때 사용할 수 있습니다:

'custom' => [
    'person.*.email' => [
        'unique' => 'Each person must have a unique e-mail address',
    ]
],

사용자 정의 유효성 검사 룰

라라벨은 다양하고 유용한 유효성 검사 룰을 제공합니다; 하지만, 여러분은 여러분만의 유효성 검사 룰을 정의하길 바랄수도 있습니다. 커스텀 유효성 검사 룰을 등록하는 방법중 하나는 Validator 파사드extend 메소드를 사용하는 것입니다. 이 메소드를 서비스 프로바이더 내에서 사용하여 커스텀 유효성 검사 룰을 등록합니다:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Validator::extend('foo', function ($attribute, $value, $parameters, $validator) {
            return $value == 'foo';
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

커스텀 유효성 검사 클로저는 4개의 인자를 받습니다: 유효성 검사를 할 필드($attribute)의 이름, 필드의 값($value), 그리고 룰에 전달될 파라미터들($parameters)의 배열, 그리고 Validator 인스턴스 입니다.

또한 클로저 대신 클래스명과 메소드명을 extend 메소드로 전달할 수도 있습니다:

Validator::extend('foo', 'FooValidator@validate');

에러 메세지 정의하기

커스텀 룰을 위한 에러 메세지 또한 정의해야 합니다. 인라인 커스텀 메세지 배열을 사용하거나 유효 검사 언어 파일에 엔트리를 추가하면 됩니다. 이 메세지는 custom 배열 안이 아닌 배열의 첫번째 레벨에 놓여야 합니다. custom 배열은 특정 속성에 따른 에러 메세지를 담당합니다:

"foo" => "Your input was invalid!",

"accepted" => "The :attribute must be accepted.",

// The rest of the validation error messages...

커스텀 유효 검사 룰을 생성할 때 종종 에러 메세지를 위한 커스텀 플레이스 홀더 대체제를 정의해야 할 수도 있습니다. 이전의 설명에 따라 커스텀 Validator를 생성하고 Validator 파사드에 replacer 메소드를 호출하십시오. 이는 서비스 프로바이더boot 메소드 안에서 할 수 있습니다:

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Validator::extend(...);

    Validator::replacer('foo', function ($message, $attribute, $rule, $parameters) {
        return str_replace(...);
    });
}

묵시적 확장

기본적으로 유효성 검사를 받는 속성이 존재하지 않거나 required 룰의 정의에 따라 빈 값을 가지고 있다면, 커스텀 확장을 포함한 정상적인 유효성 검사 룰은 실행되지 않을 것입니다. 예를 들어 null 값에는 unique 룰이 실행되지 않을 것입니다:

$rules = ['name' => 'unique'];

$input = ['name' => null];

Validator::make($input, $rules)->passes(); // true

속성이 비었을 때도 룰이 실행되기 위해서는 룰에 속성이 필요하다는 것이 내포되어 있어야 합니다. 이런 "묵시적"인 확장을 만드려면 Validator::extendImplicit() 메소드를 사용하세요:

Validator::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) {
    return $value == 'foo';
});

{note} "묵시적" 확장은 단지 속성이 필요하다는 것을 _암시(내포)_합니다. 없거나 빈 속성의 유효성을 실제로 부정하는지는 여러분이 결정합니다.