Validation

[su_heading size=”30″ align=”left” margin=”10″ class=”top”]# Introduction[/su_heading]

라라벨은 어플리케이션에 입력되는 데이터의 유효성 검사를 위하여 몇가지 방법을 제공한다. 기본적으로 라라벨의 기본 컨트롤러 클래스는 [su_label type=”black”]ValidatesRequests[/su_label] 특성을 사용한다. 이 특성은 다양하고 강력한 유효성 검사 규칙으로 입력되는 HTTP 요청의 유효성을 검사하는 편리한 메서드이다.

[su_heading size=”30″ align=”left” margin=”10″]# Validation Quickstart[/su_heading]

강력한 유효성 검사 기능에 대해 알아보기 위해 폼 유효성 검사와 사용자에게 에러 메시지를 출력하는 예제를 살펴보자.

Defining The Routes

우선 [su_label type=”black”]routes/web.php[/su_label] 파일에 다음의 라우트를 정의했다고 가정해보자.

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

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

당연히 [su_label type=”black”]get[/su_label] 라우트는 사용자에게 새로운 블로그 글을 등록하기 위한 양식을 출력하고, [su_label type=”black”]post[/su_label] 라우트는 데이터베이스에 새 블로그 글을 저장할 것이다.

Creating The Controller

작성한 라우트를 처리하는 간단한 컨트롤러를 살펴보자. 지금은 [su_label type=”black”]store[/su_label] 메서드를 비둬둔다.

<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    public function create()
    {
        return view('post.create');
    }

    public function store(Request $request)
    {
        // Validate and store the blog post...
    }
}

이제 새 블로그 게시물의 유효성 검사를 위한 로직을 [su_label type=”black”]store[/su_label] 메서드에 채울 준비가 되었다. 어플리케이션의 기본 컨트롤러 ([su_label type=”black”]App\Http\Controllers\Controller[/su_label]) 클래스를 확인하면 클래스가 [su_label type=”black”]ValidatesRequests[/su_label] 특성을 사용하는 것을 볼 수 있다. 이 특성은 모든 컨트롤러에 유용한 [su_label type=”black”]validate[/su_label] 메서드를 제공한다.

[su_label type=”black”]validate[/su_label] 메서드는 입력되는 HTTP 요청과 일련의 유효성 검사 규칙을 수용한다. 유효성 검사 규칙이 통과하면 코드는 정상적으로 수행되지만 실패할 경우 예외가 발생하고 적절한 오류 응답이 사용자에게 자동적으로 보내진다. 전형적인 HTTP 요청의 경우 리다이렉트 응답이 생성되며, AJAX 요청일 경우에는 JSON 응답이 전송된다.

[su_label type=”black”]validate[/su_label] 메서드를 보다 잘 이해하기 위해, [su_label type=”black”]store[/su_label] 메서드로 돌아가 보자.

public function store(Request $request)
{
    $this->validate($request, [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

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

보다시피 간단하게 [su_label type=”black”]validate[/su_label] 메서드에 입력되는 HTTP Request와 적용되길 원하는 유효성 검사 규칙을 전달해 주면 된다. 다시 말하지만 유효성 검사가 실패하면 적절한 응답이 자동적으로 생성되고, 유효성 검사가 통과되면 컨트롤러는 계속해서 정상적으로 실행된다.

Stopping On First Validation Failure

첫 번째 유효성 검사가 실패했을 때 유효성 검사 실행이 멈추길 원할 때가 있다. 이럴 때는 유효성 검사 속성에 [su_label type=”black”]bail[/su_label] 규칙을 추가하면 된다.

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

이 예제에서, [su_label type=”black”]title[/su_label] 속성의 [su_label type=”black”]required[/su_label] 규칙이 실패할 경우 [su_label type=”black”]unique[/su_label] 규칙을 확인하지 않는다. 규칙은 할당된 순서대로 유효성 검사가 수행된다.

A Note On Nested Attributes

HTTP 요청이 중첩된 매개변수를 포함하고 있을 경우, “.” 구문을 사용하여 유효성 검사 규칙에 지정할 수 있다.

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

Displaying The Validation Errors

입력되는 요청 매개변수가 유효성 검사 규칙에 통과하지 못하면 어떻게 될까? 라라벨은 자동으로 사용자에게 이전 페이지로 리다이렉트 시킨다. 또한 모든 유효성 검사 오류는 자동적으로 세션에 플래시 데이터로 저장된다.

[su_label type=”black”]get[/su_label] 라우트의 뷰에 명확한 오류 메시지를 제공하지 않았다. 라라벨은 세션 데이터의 오류를 검사하고, 사용 가능한 경우 뷰에 자동으로 적용하기 때문이다. [su_label type=”black”]$errors[/su_label]는 [su_label type=”black”]Illuminate\Support\MessageBag[/su_label]의 인스턴스  변수이다. 이 객체의 동작에 대한 보다 많은 정보는 이 문서를 확인해보자.

[su_note note_color=”#40749c” text_color=”#ffffff”][su_label type=”black”]$errors[/su_label] 변수는 [su_label type=”black”]Illuminate\View\Middleware\ShareErrosFromSession[/su_label] 미들웨어에 의해 뷰에 적용되며 web 미들웨어 그룹에 의해 제공된다. 이 미들웨어가 적용되었을 때 [su_label type=”black”]$errors[/su_label] 변수는 뷰에서 항상 사용 가능하며, [su_label type=”black”]$errors[/su_label] 변수가 항상 정의되어 있고 편리하고 안전하게 사용될 수 있다는 것을 예상할 수 있다.[/su_note]

예제에서, 유효성 검사가 실패했을 때 사용자는 컨트롤러의 [su_label type=”black”]create[/su_label] 메서드로 리다이렉트되어 뷰에 오류 메시지를 출력한다.

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

<h1>Create Post</h1>

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

<!-- Create Post Form -->

A Note On Optional Fields

기본적으로, 라라벨은 어플리케이션의 전역 미들웨어 스택에 [su_label type=”black”]TrimStrings[/su_label]와 [su_label type=”black”]ConvertEmptyStringsToNull[/su_label] 미들웨어를 포함합니다. 이 미들웨어들은 [su_label type=”black”]App\Http\Kernel[/su_label] 클래스에 의해 스택에 나열된다. [su_label type=”black”]null[/su_label] 값을 유효하지 않은 것으로 유효성 검사를 하는 것을 원하지 않을 경우 요청 필드에 [su_label type=”black”]nullable[/su_label]과 같이 “옵션”을 표시해야 하는 경우가 있기 때문이다.

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

이 예에서, [su_label type=”black”]publish_at[/su_label] 필드는 [su_label type=”black”]null[/su_label] 이거나 유효상 날짜 표현으로 지정했다. 만약 [su_label type=”black”]nullable[/su_label] 수식자가 규칙에 정의되지 않았다면, [su_label type=”black”]null[/su_label] 값은 유효하지 않은 날짜로 유효성 검사가 수행된다.

Customizing The Flashed Error Format

만약 유효성 검사가 실패했을 때 세션에 플래시된 유효성 검사 에러 형식을 변경하고 싶다면, 기본 컨트롤러에서 [su_label type=”black”]formatValidationErrors[/su_label]를 재정의 한다. 파일 상단에 [su_label type=”black”]Illuminate\Contracts\Validation\Validator[/su_label] 클래스를 임포트시켜야 하는 것을 잊지말아야 한다.

<?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 Requests & Validation

이 예제에서, 어플리케이션에게 데이터를 전송하기 위한 전형적인 양식을 사용했다. 그러나 많은 어플리케이션은 AJAX 요청을 사용한다. AJAX 요청 중에 [su_label type=”black”]validate[/su_label] 메서드를 사용할 때, 라라벨은 리다이렉트 응답을 생성하지 않을 것이다. 대신에, 라라벨은 모든 유효성 검사 오류를 포함한 JSON 응답을 생성한다. 이 JSON 응답은 422 HTTP 상태코드와 함께 전송된다.

 [su_heading size=”30″ align=”left” margin=”10″]# Form Request Validation[/su_heading]

Creating Form Requests

보다 복잡한 유효성 검사 시나리오를 위해 “양식 요청” 생성하는 것을 원할 수 있다. 양식 요청은 유효성 검사 로직이 포함된 사용자 정의 요청 클래스이다. 양식 요청 클래스를 생성하기 위해 [su_label type=”black”]make:request[/su_label] artisan CLI 명령어를 사용한다.

$ php artisan make:request StoreBlogPost

생성된 클래스는 [su_label type=”black”]app\Http\Requests[/su_label] 디렉토리에 위치한다. 이 디렉토리가 존재하지 않을 경우, [su_label type=”black”]make:request[/su_label] 명령어가 실행될 때 생성된다. [su_label type=”black”]rules[/su_label] 메서드에 몇 가지 유효성 검사 규칙을 추가해 보자.

public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

그렇다면 유효성 검사는 어떻게 수행될까? 컨트롤러 메서드상의 모든 요청에 타입 힌드를 주면 된다. 입력되는 양식 요청은 컨트롤러 메서드가 호출되기 전에 유효성 검사가 수행되기 때문에 컨트롤러에 어떠한 유효성 검사 로직도 채울 필요가 없다.

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

만약 유효성 검사가 실패하면, 사용자에게 이전 페이지로 리다이렉트 응답을 생성하여 전송한다. 또한 오류는 표시될 수 있도록 세션에 플래시 저장된다. 만약 요청이 AJAX 요청이었다면, JSON 표현식으로 유효성 검사 오류를 포함하여 422 HTTP 상태 코드와 함께 리턴된다.

Adding After Hooks To Form Requests

Form request에 “애프터 후크”를 추가하고 싶을 경우, [su_label type=”black”]withvalidator[/su_label] 메서드를 사용할 수 있다. 이 메서드는 유효성 검사 규칙이 실제로 수행되기 전에 어떤 메서드를 호출하기 위해 완전히 생성된 유효성 검사기를 받는다.

/**
 * 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!');
        }
    });
}

Authorizing Form Requests

또한 Form request 클래스는 [su_label type=”black”]authorize[/su_label] 메서드가 포함되어 있다. 이 메서드에서, 주어진 자원을 업데이트하기 위한 권한이 사용자에게 실제로 주어져 있는지 확인할 수 있다. 예를 들어, 사용자가 업데이트하기 위해 블로그 댓글을 소유하고 있는지 확인할 수 있다.

/**
 * 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 클래스를 확장하기 때문에 현재 인증되어 있는 사용자에 엑세스 하기 위해 [su_label type=”black”]user[/su_label] 메서드를 사용할 수 있다. 또한 위의 예제에서 [su_label type=”black”]route[/su_label] 메서드 호출을 주목해야 한다. 이 메서드는 아래의 예제에서 [su_label type=”black”]{comment}[/su_label] 매개변수와 같이 라우트로 호출되는 정의된 URI 매개변수에 엑세스를 허용한다.

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

[su_label type=”black”]authorize[/su_label] 메서드가 [su_label type=”black”]false[/su_label]를 리턴할 경우, 자동적으로 403 HTTP 상태 코드 응답이 리턴되고 컨트롤러 메서드는 실행되지 않을 것이다.

어플리케이션의 다른 부분에 인증 로직을 사용하고 싶을 경우 [su_label type=”black”]authorize[/su_label] 메서드에는 간단하게 [su_label type=”black”]true[/su_label]를 리턴시켜라.

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

Customizing The Error Format

유효성 검사가 실패했을 때 세션에 플래시된 유효성 검사 오류 형식을 사용자 정의 하고 싶을 경우, 기본 request ([su_label type=”black”]App\Http\Requests\Request[/su_label]) 에서 [su_label type=”black”]formatErrors[/su_label]를 재정의한다. 파일 상단에 [su_label type=”black”]Illuminate\Contracts\Validation\Validator[/su_label] 클래스를 import 시키는 것을 잊지 말아라.

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

Customizing The Error Messages

재정의한 [su_label type=”black”]messages[/su_label] 메서드로 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',
    ];
}

[su_heading size=”30″ align=”left” margin=”10″]Manually Creating Validators[/su_heading]

[su_label type=”black”]ValidatesRequests[/su_label] 특성의 [su_label type=”black”]validate[/su_label] 메서드를 사용하고 싶지 않을 경우, [su_label type=”black”]validator[/su_label] 파사드를 사용하여 직접 유효성 검사 인스턴스를 만들 수 있다. 파사드의 [su_label type=”black”]make[/su_label] 메서드는 새로운 유효성 검사 인스턴스를 생성한다.

<?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...
    }
}

[su_label type=”black”]make[/su_label] 메서드에 전달되는 첫 번째 매개변수는 유효성 검사를 수행하는 데이터이다. 두 번째 매개변수는 데이터에 적용될 유효성 검사 규칙이다.

검사 후 유효성 검사가 실패할 경우, 세션에 오류 메시지를 플래시 시키기 위해 [su_label type=”black”]withErrors[/su_label] 메서드를 사용한다. 이 메서드가 사용될 때, [su_label type=”info”]$errors[/su_label] 변수는 자동적으로 리다이렉션 된 뷰와 공유되며 사용자에게 손쉽게 보여줄 수 있다. [su_label type=”black”]withErrors[/su_label] 메서드는 유효성 검사, [su_label type=”black”]MessageBag[/su_label] 또는 PHP [su_label type=”info”]array[/su_label]를 허용한다.

Automatic Redirection

유효성 검사 인스턴스를 직접 만들었지만 여전히 [su_label type=”black”]ValidatesRequest[/su_label]의 특성에 의한 자동 리다이렉션의 장점 사용할 수 있는데, 유효성 검사 인스턴스에서 [su_label type=”black”]validate[/su_label] 메서드를 호출할 수 있다. 유효성 검사가 실패할 경우, 사용자는 자동적으로 리다이렉트 되거나, AJAX request 일 경우에는 JSON 응답을 리턴받게 된다.

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

Named Error Bags

한 페이지에 여러 양식이 있을 경우, 오류의 [su_label type=”black”]MessageBag[/su_label] 이름을 지정하여 특정 양식에 대한 오류 메시지를 가져올 수 있다. [su_label type=”black”]withErros[/su_label] 메서드에 두 번째 매개변수로 이름을 전달하기만 하면 된다.

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

그런 다음 [su_label type=”info”]$errors[/su_label] 변수로부터 명명된 [su_label type=”black”]MessageBag[/su_label] 인스턴스에 엑세스할 수 있다.

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

After Validation Hook

유효성 검사기는 유효성 검사가 완료된 후 콜백을 추가하여 실행할 수 있다. 이를 통해 메시지 콜렉션에 오류 메시지를 추가하고 유효성 검사를 쉽게 수행할 수 있다. 시작하려면 유효성 검사기 인스턴스의 [su_label type=”info”]after[/su_label] 메서드를 사용해라.

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

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

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

[su_heading size=”30″ align=”left” margin=”10″]Working With Error Messages[/su_heading]

[su_label type=”black”]Validator[/su_label] 인스턴스의 [su_label type=”black”]error[/su_label] 메서드가 호출되면, 오류 메시지 작업을 위한 편리한 메서드가 다양하게 있는 [su_label type=”black”]Illuminate\Support\MessageBag[/su_label]  인스턴스를 받는다. [su_label type=”info”]$errors[/su_label] 변수는 모든 뷰에서 사용할 수 있게 자동적으로 만들어진 [su_label type=”black”]MesasgeBag[/su_label] 클래스이다.

Retrieving The First Error Message For A Field

주어진 필드의 첫 번째 에러 메시지를 가져오려면, [su_label type=”black”]first[/su_label] 메서드를 사용한다.

$errors = $validator->errors();

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

Retrieving All Error Messages For A Field

주어진 필드의 모든 에러 메시지를 가져오려면, [su_label type=”black”]get[/su_label] 메서드를 사용한다.

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

배열 폼 필드를 유효성 검사할 경우, ‘*’ 문자를 사용하여 각각의 배열 요소의 모든 메시지를 가져올 수 있다.

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

Retrieving All Error Messages For All Fields

모든 필드에 대한 모든 메시지의 배열을 가져오려면, [su_label type=”black”]all[/su_label] 메서드를 사용한다.

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

Determining If Messages Exist For A Field

주어진 필드에 오류 메시지가 있는지 확인하기 위해 [su_label type=”black”]has[/su_label] 메서드를 사용할 수 있다.

Custom Error Messages

필요한 경우, 사용자 정의 오류 메시지를 유효성 검사의 기본 오류 메시지 대신에 사용할 수 있다. 사용자 정의 메시지를 지정하기 위한 몇 가지 방법이 있다. 우선 [su_label type=”black”]Validator::make[/su_label] 메서드에 세 번째 매개변수로 사용자 정의 메시지를 전달한다.

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

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

이 예제에서, [su_label type=”black”]:attribute[/su_label] 플래스 홀더에는 유효성 검사를 진행하는 필드의 실제 이름의 위치한다. 유효성 검사 메시지에서 또 다른 유용한 플래스 홀더는 다음 예와 같다.

$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',
];

Specifying A Custom Message For A Given Attribute

가끔은 특정 필드에만 사용자 정의 오류 메시지를 지정할 수도 있다. “.” 표기법을 사용하면 된다. 속성의 이름을 먼저 지정하고 다음에 규칙을 지정한다.

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

Specifying Custom Messages In Language Files

대부분의 경우, [su_label type=”black”]Validator[/su_label]에 직접 메시지를 전달하는 대신에 언어 파일에 사용자 정의 메시지를 지정한다. 그렇게 하려면 [su_label type=”black”]resources/lang/xx/validation.php[/su_label] 언어 파일내에 [su_label type=”black”]custom[/su_label] 배열에 메시지를 추가한다.

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

Specifying Custom Attributes In Language Files

사용자 정의 속성 이름을 유효성 검사 메시지의 [su_label type=”black”]:attribute[/su_label] 부분에 대체하기 위해 [su_label type=”black”]resources/lang/xx/validation.php[/su_label]  파일에서 [su_label type=”black”]attributes[/su_label] 배열에 사용자 정의 이름을 지정할 수 있다.

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

[su_heading size=”30″ align=”left” margin=”10″]Available Validation Rules[/su_heading]

아래에는 사용 가능한 유효성 검사 규칙과 함수가 나열되어 있다.

[su_row][su_column size=”1/5″]Accepted[/su_column] [su_column size=”1/5″]Active URL[/su_column] [su_column size=”1/5″]After (Date)[/su_column] [su_column size=”1/5″]After Or Equal (Date)[/su_column] [su_column size=”1/5″]Alpha[/su_column][/su_row]

accepted

유효성 검사 필드는 yes, on, 1 또는 true 이어야 한다. 이 규칙은 “서비스 약관” 승인 여부를 확인하는데 유용하다.

active_url

유효성 검사 필드는 [su_label type=”black”]dns_get_record[/su_label] PHP 함수에 일치하는 유효한 A 또는 AAAA 레코드여야 한다.