in

Restricts the value to a fixed list of allowed options.

Signature
in:foo,bar,...

Parameters

ParameterTypeDescription
$valuesstringA comma-separated list of acceptable values. Rule::in() accepts an array and quotes each entry so commas and quotes inside a value survive.

Errors

Nothing on its own; a failure surfaces as Illuminate\Validation\ValidationException when run through validate() or a form request.

The field under validation must be included in the given list of values. Since this rule often requires you to implode an array, the Rule::in method may be used to fluently construct it.

Always prefer Rule::in

The string form splits on commas, so any value that itself contains a comma is silently broken into two options — and the field it was meant to allow now fails. Rule::in(['medium, large']) wraps each entry in quotes and escapes internal ones, so the list survives intact. Values coming from a database, a config array or user-facing labels should never be imploded by hand.

Validating array members

When in is combined with the array rule, every value in the input array must appear in the list. Given 'airports' => ['NYC', 'LAS'] and 'airports.*' => Rule::in(['NYC', 'LIT']), the LAS entry is invalid.

Two things that surprise people

The default message is "The selected field is invalid." — it never lists the permitted values. Supply a custom message when an API consumer needs them.

For a backed enum, the dedicated Rule::enum(Status::class) rule is a better fit than imploding cases(), and it casts the value for you.

Example

Example · php
<?php

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$sizes = ['small', 'medium, large'];   // note the comma inside a value

// String form: the comma splits that value into two separate options.
var_dump(Validator::make(['size' => 'medium, large'], [
    'size' => 'in:' . implode(',', $sizes),
])->passes());

// Rule::in quotes and escapes each entry, so it survives.
var_dump(Validator::make(['size' => 'medium, large'], [
    'size' => [Rule::in($sizes)],
])->passes());

// bool(false)
// bool(true)

When to use it

  • Restricting a status field to draft, published or archived.
  • Validating a sort parameter against the columns your query actually supports.
  • Checking a currency code against a list loaded from configuration.
  • Ensuring every element of a submitted array of airport codes is recognised.

Frequently asked questions

Why should I use Rule::in instead of the in: string?

Because the string form splits on commas, so any allowed value containing a comma is broken into two bogus options and the real value is rejected. `Rule::in()` takes an array and quotes each entry, escaping internal quotes, so values with commas survive.

How do I show the allowed values in the error message?

Set a custom message for the rule, such as `'sort.in' => 'The :attribute must be one of: created_at, title, views.'`. The default message is "The selected :attribute is invalid." and deliberately never enumerates the list.

How do I validate that every item in an array is allowed?

Put the `in` rule on the wildcard key rather than the field itself: `'airports' => ['required', 'array']` plus `'airports.*' => Rule::in([...])`. Errors are then reported per index, such as `airports.1`.

More examples

Validating every member of an array

LAS is not in the permitted list, and the wildcard rule reports the failing index so the client can highlight the right row. Putting `in` on `airports` itself rather than `airports.*` would instead compare the whole array against the list and always fail.

Example · php
<?php

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$input = ['airports' => ['NYC', 'LAS']];

$validator = Validator::make($input, [
    'airports'   => ['required', 'array'],
    'airports.*' => Rule::in(['NYC', 'LIT']),
]);

var_dump($validator->passes());
print_r($validator->errors()->toArray());

// bool(false)
// Array
// (
//     [airports.1] => Array
//         (
//             [0] => The selected airports.1 is invalid.
//         )
// )

A safe sort parameter, and a custom message

An `in` whitelist is what makes it safe to feed a request parameter into `orderBy()`. The custom `sort.in` message replaces the unhelpful default, which would only have said "The selected sort is invalid." — a client debugging a 422 has no way to guess the allowed set otherwise.

Example · php
<?php

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$sortable = ['created_at', 'title', 'views'];

$validator = Validator::make(['sort' => 'password'], [
    'sort'      => ['sometimes', Rule::in($sortable)],
    'direction' => ['sometimes', Rule::in(['asc', 'desc'])],
], [
    'sort.in' => 'The :attribute must be one of: ' . implode(', ', $sortable) . '.',
]);

print_r($validator->errors()->all());

// Array
// (
//     [0] => The sort must be one of: created_at, title, views.
// )

// $query->orderBy($validator->validated()['sort'] ?? 'created_at');

Backed enums: prefer Rule::enum

Both accept the same three strings, but `Rule::enum` returns a `Status` instance from `validated()` rather than a raw string, and it stays correct when a case is added to the enum. Reach for `Rule::in` when the allowed set comes from config or a database rather than an enum.

Example · php
<?php

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

enum Status: string
{
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';
}

// Workable, but you are re-deriving the list by hand.
$a = Validator::make(['status' => 'published'], [
    'status' => [Rule::in(array_column(Status::cases(), 'value'))],
]);

// Better: the dedicated rule, which also casts the value.
$b = Validator::make(['status' => 'published'], [
    'status' => [Rule::enum(Status::class)],
]);

var_dump($a->passes());
var_dump($b->validated()['status'] instanceof Status);

// bool(true)
// bool(true)

Discussion

  • Be the first to comment on this lesson.