agentsclimarketplace

Laravel validation

Skill ComeOnOliver/skillshub/skills/riasvdv/skills/laravel-validation

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill laravel-validation

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

8.3 KB, ~2.2k tokens by cl100k_base, as published. Nobody here has run it

Laravel Validation

Always use array syntax for rules, not pipe-delimited strings. Arrays are easier to read, diff, and extend — and required when using Rule objects or closures.

// WRONG:
'email' => 'required|email|unique:users',

// CORRECT:
'email' => ['required', 'email', 'unique:users'],

Quick Decision Guide

"How do I validate?"

ScenarioApproach
Simple controller validation$request->validate([...])
Reusable/complex validationForm Request class
Outside HTTP request (CLI, jobs)Validator::make($data, $rules)
Validate and get safe data$request->safe() for ValidatedInput object
Validate but keep goingValidator::make()->validate() or check ->fails()

"Which rule do I need?"

Presence & optionality:

NeedRule
Must be present and non-emptyrequired
Required only if presentsometimes
May be nullnullable
Must be present (even if empty)present
Must not be in inputmissing
Required when other field has valuerequired_if:field,value
Required when other field is absentrequired_without:field
Exclude from validated outputexclude

Type constraints:

NeedRule
Stringstring
Integerinteger
Numeric (int, float, string)numeric
Booleanboolean
Arrayarray
Sequential list (0-indexed)list
Datedate or date_format:Y-m-d
File uploadfile
Imageimage
Emailemail
URLurl
JSONjson
UUIDuuid

Size & range:

NeedRule
Min/max length, value, count, or KBmin:n / max:n
Exact sizesize:n
Between rangebetween:min,max
Compare to another fieldgt:field / gte:field / lt:field / lte:field

Database:

NeedRule
Must exist in tableexists:table,column or Rule::exists(...)
Must be unique in tableunique:table,column or Rule::unique(...)

Validated Data Access

// Get only validated fields
$validated = $request->validated();

// Get ValidatedInput object (supports only/except/merge/etc.)
$safe = $request->safe();
$safe->only(['name', 'email']);
$safe->except(['password']);
$safe->merge(['ip' => $request->ip()]);

Common Pitfalls

1. Missing nullable on optional fields

Laravel's ConvertEmptyStringsToNull middleware converts "" to null. Without nullable, empty optional fields fail validation.

// WRONG: empty string becomes null, fails 'string' rule
'bio' => ['string', 'max:500'],

// CORRECT:
'bio' => ['nullable', 'string', 'max:500'],

2. sometimes vs nullable vs required

// required: MUST be present and non-empty
'name' => ['required', 'string'],

// nullable: can be present as null
'nickname' => ['nullable', 'string'],

// sometimes: only validate IF the field is in the input at all
// (useful for PATCH requests where fields are optional)
'email' => ['sometimes', 'required', 'email'],

3. Unsafe unique ignore

Never pass user-controlled input to ignore():

// DANGEROUS: SQL injection risk
Rule::unique('users')->ignore($request->input('id'))

// SAFE: use the authenticated model
Rule::unique('users')->ignore($user->id)

4. bail placement

bail must be the first rule to stop processing on first failure:

// WRONG: bail has no effect here
'email' => ['required', 'bail', 'email', 'unique:users'],

// CORRECT: bail first
'email' => ['bail', 'required', 'email', 'unique:users'],

5. Array vs nested validation confusion

// Validates the array itself
'tags' => ['required', 'array', 'min:1'],

// Validates each item IN the array
'tags.*' => ['string', 'max:50'],

// Nested objects in array
'users.*.email' => ['required', 'email'],
'users.*.roles.*' => ['exists:roles,name'],

6. exists / unique with soft deletes

// Ignores soft-deleted records (default counts them as existing)
Rule::unique('users', 'email')->withoutTrashed()

// Only check non-deleted records exist
Rule::exists('users', 'id')->whereNull('deleted_at')

7. Date comparison with field references

// Compare against another field, not a literal date
'end_date' => ['required', 'date', 'after:start_date'],

// Compare against a literal date
'start_date' => ['required', 'date', 'after:2024-01-01'],

// Use after_or_equal when same-day should be valid
'checkout' => ['required', 'date', 'after_or_equal:checkin'],

Rule Builders

Use fluent builders instead of string rules for complex validation. See references/rule-builders.md for the full API of every builder.

Password

use Illuminate\Validation\Rules\Password;

// Define defaults (typically in AppServiceProvider::boot)
Password::defaults(fn () => Password::min(8)->uncompromised());

// Use in rules
'password' => ['required', 'confirmed', Password::default()],

// Full chain
'password' => ['required', Password::min(8)
    ->letters()
    ->mixedCase()
    ->numbers()
    ->symbols()
    ->uncompromised(3)], // min 3 appearances in breach DB

File

use Illuminate\Validation\Rules\File;

'document' => ['required', File::types(['pdf', 'docx'])->max('10mb')],
'avatar' => ['required', Rule::imageFile()->dimensions(Rule::dimensions()->maxWidth(2000))],

Enum

'status' => [Rule::enum(OrderStatus::class)->except([OrderStatus::Cancelled])],

Date & Numeric

'start_date' => [Rule::date()->afterToday()->format('Y-m-d')],
'price' => [Rule::numeric()->decimal(2)->min(0)->max(99999.99)],
'email' => [Rule::email()->rfcCompliant()->validateMxRecord()],

Conditional Validation

use Illuminate\Validation\Rule;

$request->validate([
    'role' => ['required', 'string'],
    // Required only when role is admin
    'admin_code' => [Rule::requiredIf($request->role === 'admin')],

    // Using closures for complex conditions
    'company' => [Rule::requiredIf(fn () => $user->isBusinessAccount())],

    // Exclude from output when condition met
    'coupon' => ['exclude_if:type,free', 'required', 'string'],
]);

After validation hooks

$validator = Validator::make($data, $rules);

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

Custom Rules

Rule object (recommended)

php artisan make:rule Uppercase
php artisan make:rule Uppercase --implicit  # runs even on empty values
class Uppercase implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (strtoupper($value) !== $value) {
            $fail('The :attribute must be uppercase.');
        }
    }
}

// Usage
'name' => ['required', new Uppercase],

Closure rule (one-off)

'title' => [
    'required',
    function (string $attribute, mixed $value, Closure $fail) {
        if ($value === 'foo') {
            $fail("The {$attribute} is invalid.");
        }
    },
],

Custom Error Messages

// Inline
$request->validate([
    'email' => ['required', 'email'],
], [
    'email.required' => 'We need your email address.',
    'email.email' => 'That doesn\'t look like a valid email.',
]);

// In Form Request
public function messages(): array
{
    return [
        'title.required' => 'A title is required.',
        'body.required' => 'A message body is required.',
    ];
}

// Custom attribute names
public function attributes(): array
{
    return [
        'email' => 'email address',
    ];
}

// Array position placeholder
'photos.*.description.required' => 'Please describe photo #:position.',

Reference Files

  • All validation rules: See references/rules.md for every built-in rule with signatures and descriptions
  • Rule class & fluent builders: See references/rule-builders.md for Rule::unique(), Rule::exists(), Password::, File::, Rule::date(), Rule::numeric(), Rule::email(), Rule::enum(), Rule::dimensions(), and all other fluent builder APIs
  • Form Requests: See references/form-requests.md for Form Request patterns, methods, and advanced usage

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.