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

Jacobs's avatar

Validation passes, while it shouldn't?

Hey, as the title says, something seems to be wrong about my validation. It also seems to ignore the 'max:32' rule. I'm trying to achieve each input to be a string, not null, have a max value based on config and only contain letters, dashes, spaces.

        for($i=1; $i<4; $i++) {
            $rules[$i] = 'required|string|max:' . config('aac.guilds.rankLengthMax') . '|regex:/^[a-zA-Z-\s]*$/';
        }
        $this->validate(
            $request,
            [
                $rules
            ],
            [
                '*.required' => 'Rank name cannot be empty.',
                '*.string' => 'Rank name has to be a string.',
                '*.max' => 'Rank name can only be a maximum length of 32 letters.',
                '*.regex' => 'Rank name can only contain letters, spaces and dashes.'
            ]
        );
        $input = $request->only('1', '2', '3');
        dd($rules, $input);

Outputs:

array:3 [▼
  1 => "required|string|max:32|regex:/^[a-zA-Z-\s]*$/"
  2 => "required|string|max:32|regex:/^[a-zA-Z-\s]*$/"
  3 => "required|string|max:32|regex:/^[a-zA-Z-\s]*$/"
]
array:3 [▼
  1 => "Memberdfgst"
  2 => "Vice-Leadert"
  3 => "456"
]

However it should not pass, but it does. Inputs have to be named 1,2,3 as those equal the 'level' column in database.

0 likes
16 replies
lostdreamer_nl's avatar

Why do you have the extra array around your $rules ?

        $this->validate(
            $request,
            [
                $rules
            ],
            [
                '*.required' => 'Rank name cannot be empty.',
                '*.string' => 'Rank name has to be a string.',
                '*.max' => 'Rank name can only be a maximum length of 32 letters.',
                '*.regex' => 'Rank name can only contain letters, spaces and dashes.'
            ]
        );

I think this should be :


        $this->validate(
            $request,
            $rules,
            [
                '*.required' => 'Rank name cannot be empty.',
                '*.string' => 'Rank name has to be a string.',
                '*.max' => 'Rank name can only be a maximum length of 32 letters.',
                '*.regex' => 'Rank name can only contain letters, spaces and dashes.'
            ]
        );
Cronix's avatar

$rules is already an array, but when you validate it, you put $rules in another array.

try

$this->validate(
    $request,
    $rules,
    [
        '*.required' => 'Rank name cannot be empty.',
        '*.string' => 'Rank name has to be a string.',
        '*.max' => 'Rank name can only be a maximum length of 32 letters.',
        '*.regex' => 'Rank name can only contain letters, spaces and dashes.'
    ]
);
Jacobs's avatar

With that, I just get redirected back with no error message.

Cronix's avatar

And in the view... you're displaying the error messages? If you get redirected, that would indicate the validation didn't pass and is probably now working.

Jacobs's avatar

Yes, I always do.

            @if ($errors->any())
                <br>
                <div class="alert alert-danger">
                    <ul>
                        @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif
            @if(session()->has('message'))
                <br>
                <div class="alert alert-success">
                    {{ session()->get('message') }}
                </div>
            @endif 
Jacobs's avatar

Also, log returns this:

[2018-07-30 17:44:56] local.ERROR: The Response content must be a string or object implementing __toString(), "boolean" given. {"userId":1,"email":"<>","exception":"[object] (UnexpectedValueException(code: 0): The Response content must be a string or object implementing __toString(), \"boolean\" given. at E:\xampp\htdocs\ThanaAAC\vendor\symfony\http-foundation\Response.php:384)
[stacktrace]
Cronix's avatar

Ok, so now you have a problem where you are returning the response back to the browser. You're not showing any of that code though.

Jacobs's avatar

I don't see how is that relevant as the database data do not get updated, nor does the dd() go through. Also, I'm pretty sure the $rules has to be in additional array, otherwise it breaks like I've posted before.

    public function rank(Request $request)
    {
        for($i=1; $i<4; $i++) {
            $rules[$i] = 'required|string|max:' . config('aac.guilds.rankLengthMax') . '|regex:/^[a-zA-Z-\s]*$/';
        }
        $this->validate(
            $request,
            $rules,
            [
                '*.required' => 'Rank name cannot be empty.',
                '*.string' => 'Rank name has to be a string.',
                '*.max' => 'Rank name can only be a maximum length of 32 letters.',
                '*.regex' => 'Rank name can only contain letters, spaces and dashes.'
            ]
        );
        $input = $request->only('1', '2', '3');
        dd($rules, $input);
        $guild = Session::get('guild');
        if(!$guild)
            return back()->withErrors('The guild session has expired.');
        $guildRanks = GuildRank::where('guild_id', $guild->id)->orderBy('level', 'asc')->get();
        $guildRanks->each(function ($rank) use ($input) {
            $rank->update(['name' => $input[$rank->level]]);
        });
        return back()->with('message', 'Guild ranks have been successfully changed.');
    }
Cronix's avatar
if(!$guild)
            return back()->withErrors('The guild session has expired.');

I think that's your problem now. You're not using withErrors correctly? You're just sending a string.

After checking if the request validation failed, you may use the withErrors method to flash the error messages to the session. When using this method, the $errors variable will automatically be shared with your views after redirection, allowing you to easily display them back to the user. The withErrors method accepts a validator, a MessageBag, or a PHP array.

https://laravel.com/docs/5.6/validation#manually-creating-validators

Cronix's avatar

Just send a message back like you are here

return back()->with('message', 'Guild ranks have been successfully changed.');
if(!$guild)
            return back()->with('message', 'The guild session has expired.');

Then it will be displayed in your code here

@if(session()->has('message'))
    <br>
    <div class="alert alert-success">
        {{ session()->get('message') }}
    </div>
@endif 

But really, I'd put that as the very first thing in the method. There is no point in validating data and wasting cpu cycles if there is an invalid/unset guild since all you do is redirect with an error message if it's not valid.

public function rank(Request $request)
{
    $guild = Session::get('guild');
    if(!$guild)
        return back()->withErrors('The guild session has expired.');

    //rest of your code
Jacobs's avatar

I actually haven't had a problem with that ever, however what I've noticed is that somehow all my pages on any request seem to be reloading twice, thus the error gets flushed.

I haven't touched any core functionality of the project, just added a new route, something seems to have broken.

Also, good point about that guild thingy, changed it.

lostdreamer_nl's avatar

@Jacobs

I found the problem, I just tested it locally and it seems that the validation in laravel does not like number named form inputs.

This is what I get with my validation tests:

// 3 fields called test1, test2, test3 and rules with those names as well

    #messages: MessageBag {#632 ▼
      #messages: array:1 [▼
        "test3" => array:1 [▼
          0 => "Rank name can only contain letters, spaces and dashes."
        ]
      ]
      #format: ":message"
    }
    #data: array:3 [▼
      "test1" => "test"
      "test2" => "asdasdqwe"
      "test3" => "123654987"
    ]

But now the validation exception of the fields called 1, 2, 3 and the same rules:


    #messages: MessageBag {#632 ▼
      #messages: array:1 [▼
        0 => array:1 [▼
          0 => "Rank name cannot be empty."
        ]
      ]
      #format: ":message"
    }
    #data: array:3 [▼
      1 => "test"
      2 => "asdasdqwe"
      3 => "123654987"
    ]

The keys for the error is now 0...... And you don't have that field.

The solution : Change your input fieldnames to the complete fieldnames you're using in your database (I'm hoping your not using 1, 2 and 3 as DB columns)

Also, a good debug method for those validations:

Try {
        $this->validate(
            $request,
            $rules,
            [
                '*.required' => 'Rank name cannot be empty.',
                '*.string' => 'Rank name has to be a string.',
                '*.max' => 'Rank name can only be a maximum length of 32 letters.',
                '*.regex' => 'Rank name can only contain letters, spaces and dashes.'
            ]
        );
} catch(\Exception $e) {
    dd($e);
}

ps. The $rules should not have [ ] arround them in the call to $this->validate()

1 like
Jacobs's avatar

Tested, you're right about the [] on $rules, also changed the input name's to level_ID.

Still a new issue popped up that refreshes all pages twice on any request - e.g. refresh the page via F5, it refreshes twice, get returned back, refreshes twice => error message gets flushed.

Tried clearing all caches aswell, no progress.

lostdreamer_nl's avatar

weird one that one..... I got that as well a few too many times.....

Using firefox ?

Try completely restarting the browser.... gets me every time (I got that behavior about 10 times already, can't find out what starts it)

Cronix's avatar

Be advised: numbered input names are invalid, according to the w3c any input field's name should always start with a alphabetical character.

I don't think that's true for attribute names (it is for ID's). I believe it's laravels array syntax messing it, or how it's processing the rules/messages (since it allows a dot syntax). I can't find anything in the rfc's that stipulate a name attribute can't start with a number. It works in regular html/php.

Do you have a link?

All I could find was

If the [name] attribute is specified, its value must not be the empty string.

The name content attribute gives the name of the form control, as used in §4.10.21 Form submission and in the form element’s elements object. If the attribute is specified, its value must not be the empty string.

https://www.w3.org/TR/html5/sec-forms.html#element-attrdef-formelements-name

lostdreamer_nl's avatar

@Cronix Damnit, I knew I should have checked before posting, you're right I was thinking about the id attributes, ooh well better to learn than to keep wrong assumptions :)

Any cdata should be able to go in there, except for . (dot) most browsers seem to replace those with _ (just quickly tested in FF to make sure)

Please or to participate in this conversation.