0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravelでバリデーションに引っかかった項目を取得する方法

Posted at

概要

laravelのバリデーションに引っかかった項目を取得する方法を書こうと思う。

この記事を読むと、バリデーションに引っかかったもののみ、nullとして扱いたいといったようなユースケースに対応できるようになる。

動作環境

laravel: 10.47
php: 8.2

まず結論から

$validation->invalid();を使用することで、バリデーションに引っかかった項目を取得することができる。

/**
 * Store a new blog post.
 */
public function store(StorePostRequest $request): RedirectResponse
{
    $rules = $this->getNullInsertIfValidationFailRule();
    $validation = Validator::make($request->all(), $rules);

    // ここでバリデーションに引っかかったフィールドを取得することができる
    $failFields = $validation->invalid();

    
    // keyが$failFieldsに存在する場合は、null。そうでない場合は$requestから取得する
    $name = array_key_exists('name', $failFields) ? null : $request->input('name');
    $email = array_key_exists('email', $failFields) ? null : $request->input('email');
 
    // Store the blog post...
 
    return redirect('/posts');
}


private function getNullInsertIfValidationFailRule(): array
{
    return [
        'name' => ['present', 'nullable', 'string', 'max:50'],
        'email' => ['present', 'nullable', 'string', 'max:255'],
    ];
}

経緯

laravelのドキュメントを読んでいると、validateされた項目を取得するコードを見つけた。
この処理を詳しく見ていく。

/**
 * Store a new blog post.
 */
public function store(StorePostRequest $request): RedirectResponse
{
    // The incoming request is valid...
 
    // Retrieve the validated input data...
    $validated = $request->validated();
 
    // Retrieve a portion of the validated input data...
    $validated = $request->safe()->only(['name', 'email']);
    $validated = $request->safe()->except(['name', 'email']);
 
    // Store the blog post...
 
    return redirect('/posts');
}

Validation - Laravel 10.x - The PHP Framework For Web Artisansから引用

$request->validated()を中身を読む

$this->invalid()が真である場合、exceptionを投げるようなコードが書かれている。
どうやら、invalid()がバリデーションルールにリクエスト値が適合しているか判定しているメソッドのようだということがわかる。

public function validated()
    {
        throw_if($this->invalid(), $this->exception, $this);

        $results = [];

        $missingValue = new stdClass;

        foreach ($this->getRules() as $key => $rules) {
            $value = data_get($this->getData(), $key, $missingValue);

            if ($this->excludeUnvalidatedArrayKeys &&
                in_array('array', $rules) &&
                $value !== null &&
                ! empty(preg_grep('/^'.preg_quote($key, '/').'\.+/', array_keys($this->getRules())))) {
                continue;
            }

            if ($value !== $missingValue) {
                Arr::set($results, $key, $value);
            }
        }

        return $this->replacePlaceholders($results);
    }

$this->invalid()の中身を読む

コードを読むと失敗した項目をkeyにした配列を返してくれることがわかる。
メソッドもpublicなので、こちらをそのまま呼べば、バリデーションに引っかかった項目を取得できそうだ。

/**
 * Returns the data which was invalid.
 *
 * @return array
 */
public function invalid()
{
    if (! $this->messages) {
        $this->passes();
    }

    $invalid = array_intersect_key(
        $this->data, $this->attributesThatHaveMessages()
    );

    $result = [];

    $failed = Arr::only(Arr::dot($invalid), array_keys($this->failed()));

    foreach ($failed as $key => $failure) {
        Arr::set($result, $key, $failure);
    }

    return $result;
}

まとめ

なかなか使い所が難しいユースケースであるが、バリデーションに引っかかった場合の項目を取得するといったことができることがわかった。

私が見つけられなかっただけかもしれないが、laravelドキュメントに書かれていない情報と思ったので今回書いてみました。

この記事が役に立ったと思っていただけたのであれば、いいね下さい!!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?