laravel-validation
When to use
Use when creating FormRequests, validation rules, or custom rule objects.
Do NOT use when:
- Authorization logic only (use
securityskill) - API response format (use
api-designskill)
Procedure: Create a FormRequest
Step 0: Inspect
- Check existing FormRequests — match style, naming, authorization, rule structure.
- Check existing custom rules — reuse before creating new ones.
- Check API error response format — match it.
Step 1: Create the class
- Name:
{Action}{Entity}Request— e.g.CreateProjectRequest. - Implement
authorize()using Policies. - Implement
rules()with array syntax — never pipe-separated. - Use
prepareForValidation()only when normalization is truly necessary.
Step 2: Rules
- Use Laravel's
Illuminate\Validation\Rulesclasses where possible. - Keep rules explicit — prefer clarity over cleverness.
- For nested arrays: validate structure AND leaf values.
- Extract custom rule objects for complex/reusable logic.
Step 3: Test
- Test required fields, invalid formats, boundary conditions, conditional rules.
- Test authorization where relevant.
- Use focused tests per validation concern.
Conventions
→ See guideline php/validations.md for array syntax, route params, property mapping, custom rules.
Output format
- FormRequest class with rules, messages, and authorization
- Custom Rule object if validation logic is complex
Gotcha
required≠ notnullable—requiredmeans present,nullablemeans value can be null.- Custom Rule objects must return
$failcallback, not throw exceptions. - Don't validate data you already trust (e.g., from a verified internal service).
Do NOT
- Do NOT validate in controllers — use FormRequest classes.
- Do NOT use
$request->all()— use$request->validated(). - Do NOT put business logic in validation classes.
Verification
Confirm new rules with a concrete probe: a Pest feature test that POSTs with curl-shaped payloads through the browser/HTTP client, or a phpunit/pest run against the FormRequest. Add at least one negative case per rule (missing, wrong type, boundary). Never claim rules work without running them.
Anti-bruteforce — diagnose before retry
When a rule fires unexpectedly, do not blindly toggle required / nullable / sometimes until tests pass. Print $request->all() once, compare against the rule set, identify the root cause, then make a targeted fix.
Clarification guard — ambiguous field → ask
If a field's intent is unclear (is tags a CSV string, an array, or JSON? is email required at create or only at update?), ask the user or check the existing schema / API contract before guessing. Hidden assumptions in validation rules surface as production 422s.
Auto-trigger keywords
- validation
- Form Request
- validation rules
- custom rule