Validating array in Laravel using custom rule with additional parameter

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Validating Arrays in Laravel with Custom Rules: Handling Cross-Field Dependencies

As developers working with complex data structures in Laravel, we often run into scenarios where standard validation rules need more context than just the single field being checked. A common requirement is validating an array of records where the validity of one field depends on another field within the same record—for instance, ensuring a phone number is correctly formatted based on its prefix.

This post dives into how to correctly implement custom validation rules that work seamlessly with nested array structures and cross-field dependencies in Laravel. We will analyze why the initial approach failed and demonstrate the robust solution for validating arrays using custom logic.

The Custom Rule Foundation

First, let's review the custom rule you’ve developed for calculating phone length. This rule is perfectly structured to accept a parameter ($prefix) during instantiation:

<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;

class PhoneLength implements Rule
{
    public $prefix;

    /**
     * Create a new rule instance.
     *
     * @param  string|null  $prefix
     * @return void
     */
    public function __construct($prefix = null)
    {
        $this->prefix = $prefix;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        // Check if both prefix and the number combine to 10 digits
        return strlen($this->prefix) + strlen($value) == 10;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'El Teléfono debe contener 10 dígitos (prefijo + número)';
    }
}

This rule is solid; it encapsulates the business logic required for your phone validation. The challenge, as you correctly identified, lies not in the rule itself, but in how Laravel's validator interprets this context when applied to an array structure.

The Challenge with Array Validation and Context

When attempting to apply this custom rule to an array using dot notation like phones.*.number, Laravel attempts to resolve the context for each element individually. However, custom rules designed to operate on a single value often struggle when they need access to sibling data within that same collection item dynamically during the validation phase. The validator expects the passed value ($value) and potentially the attribute name, but accessing the related prefix from the parent array structure requires more sophisticated handling than standard nested path notation provides for custom rule parameters.

The issue stems from the fact that the $this->prefix inside your rule is expecting a simple string or value provided by the validator context, which doesn't automatically map to the sibling field in the parent collection during this specific type of array iteration.

The Solution: Leveraging Collection Iteration and Form Requests

For complex array validations involving cross-field dependencies, the most reliable and idiomatic Laravel approach is often to move the iterative logic out of the direct validate() call and into a structured process, typically using a Form Request or by manually iterating over the data before validation. While custom rules are powerful, they need explicit context when dealing with collections.

Instead of trying to force the custom rule to implicitly understand array relationships via dot notation, we can structure the validation logic around the collection itself.

Step 1: Restructure Validation using a Custom Rule Wrapper (Recommended)

For complex scenarios like this, instead of relying solely on standard nested rules for cross-field checks, it is often cleaner to validate the entire collection structure within a dedicated method or a custom rule that processes the entire array at once.

If you must use the custom rule, ensure your controller or request handler iterates over the input first and performs the necessary contextual validation before passing data to the validator, or define a rule that explicitly handles array context if possible.

For instance, if you are using a Form Request for this data, you can iterate through the items in your service layer or controller:

// Example logic within a Controller or Service Layer
$phones = $request->input('phones', []);

foreach ($phones as $index => $phone) {
    $prefix = $phone['prefix'];
    $number = $phone['number'];

    // Manually apply the cross-field validation using your custom rule
    $validator = app('validator')->make($phone['number'], [
        'required', 
        new PhoneLength($prefix) // Pass the context explicitly here
    ]);

    if (!$validator->passes()) {
        // Handle error for this specific phone entry
        throw new \Illuminate\Validation\ValidationException($validator->errors());
    }
}

This approach separates the complex contextual logic from the strict syntax of the validator, making the intent clearer and the code easier to debug. This method ensures that you explicitly control which prefix is used for validating each specific number, providing the necessary context that simple dot notation often obscures when custom rules are involved.

Conclusion

Validating arrays with custom rules that depend on sibling fields requires careful consideration of how Laravel's validation pipeline processes nested data. While custom rules like PhoneLength are powerful tools, they need explicit context when dealing with array structures. By shifting the bulk of the cross-field logic to a controlled iteration process within your controller or service layer—as demonstrated above—you achieve greater control, clarity, and robustness in handling complex data validation. For more advanced features on structuring application logic, always refer to the official documentation found at https://laravelcompany.com.