Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SigalZ's avatar

Laravel Excel package validation help request

Hello, Using laravel 12 and the package: Laravel Excel.

https://docs.laravel-excel.com/3.1/imports/validation.html

I have an excel file with these column names:

Batch, Time, Profile, Beans, In (g), Out (g)

I need to check that the value in the 'Beans' column exists in the database and that there is a value in the 'Out (g)' column.

The documentation says:

"Configuring the validator

If you want to add conditional validation or complex validation that cannot be expressed through rules you can configure the validator similar to how you would do this with a Form request (opens new window)

Manual validation

You can use $validator->getData() to get access to the data under validation

class UsersImport implements WithValidation
{
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            if ($this->somethingElseIsInvalid()) {
                $validator->errors()->add('field', 'Something is wrong with this field!');
            }
        });

        // or...

        $validator->sometimes('*.email', 'required', $this->someConditionalRequirement());
    }
}

"

When I test it, I get this error:

TypeError vendor\maatwebsite\excel\src\Validators\Failure.php:36

Maatwebsite\Excel\Validators\Failure::__construct(): Argument #1 ($row) must be of type int, string given, called in C:\wamp64\www\mysite.local\vendor\maatwebsite\excel\src\Validators\RowValidator.php on line 55

In my blade:

@if ($errors->any())
                        <div class="alert alert-danger">
                            <p>There are errors in the file you uploaded</p>
                            <ul>
                            @foreach ($errors->all() as $error)
                                <li>{{$error}}</li>
                            @endforeach
                            </ul>
                        </div>
                    @endif

My Import class:

Can anyone please help?

0 likes
2 replies
ghabriel25's avatar

Note that you're providing wrong field name. Its out_g not Green bean

$validator->errors()->add('out_g', ...);

Its the package itself that wrongly use strtok which returns string or false, but the Failure class constructor requires the row to be int (type hinted)

public function __construct(int $row, string $attribute, array $errors, array $values = [])
{
    $this->row       = $row;
    $this->attribute = $attribute;
    $this->errors    = $errors;
    $this->values    = $values;
}
} catch (IlluminateValidationException $e) {
    $failures = [];
    foreach ($e->errors() as $attribute => $messages) {
        $row = strtok($attribute, '.'); // return string or false
        $attributeName = strtok('');
        $attributeName = $attributes['*.' . $attributeName] ?? $attributeName;

        $failures[] = new Failure(
            $row, // this should be int
            $attributeName,
            str_replace($attribute, $attributeName, $messages),
            $rows[$row] ?? []
        );
    }

It will throw an error if its not numeric

function showAge(int $age) {
    echo $age;
}

showAge('12'); // output 12 or error if using declare(strict_types = 1);
showAge('abc'); // error
imrandevbd's avatar

That error is popping up because you're adding a manual error to the validator without a numeric key. Laravel Excel expects the attribute name to follow a specific pattern (like row_number.column) so it can parse the row index. When you just pass 'Green Bean', strtok fails to find a numeric row index, passing a string to the Failure constructor instead.

Also, your current logic for checking the bean in the collection method won't work for validation because rules() and withValidator() run before the collection() method even touches the data.

namespace App\Imports;

use Maatwebsite\Excel\Concerns\ToCollection; use Maatwebsite\Excel\Concerns\WithHeadingRow; use Maatwebsite\Excel\Concerns\WithValidation; use Illuminate\Support\Collection;

class RoastImport implements ToCollection, WithHeadingRow, WithValidation { public function collection(Collection $rows) { // Your import logic here }

public function rules(): array
{
    return [
        // 'beans' matches the slugified header 'Beans'
        'beans' => ['required', 'exists:green_beans,name'],
        // 'out_g' matches 'Out (g)'
        'out_g' => ['required', 'numeric'],
    ];
}

public function customValidationMessages()
{
    return [
        'beans.exists' => 'The selected Green Bean is invalid.',
        'out_g.required' => 'The Out (g) column cannot be empty.',
    ];
}

}

Please or to participate in this conversation.