trungtranqn91's avatar

Validate count max value with text include break line (new line)

Due to the way strlen work, line breaks count as two characters in PHP, but not in Javascript. This can lead to confusion for users who type right up to the limit, click submit, and then page reload without error . even though the Javascript counter doesn't think so.

ex:

Input text:

abcd

efghi

=> 10 character

Validation:

$rules = [
	'text' => 'max:10',
]

Validate by JS is ok . But laravel is not passed.

I realize the break line will be converted to \r\n . That why php count it 2 . Anyone know about this issue please give me the solution. Thank a lot !!!

0 likes
9 replies
Niush's avatar

Line Break, Space, Tabs all are counted in validation as a character. Database will also count that as a character.

And, so does JavaScript. What, validation are you using in JavaScript? Make sure that front-end validator is counting these as a character instead.

1 like
MichalOravec's avatar

When you want to use just max 10 chars, then instead of <textarea> just use <input type="text">

1 like
trungtranqn91's avatar

@niush I mean I use JS ember in view by JsValidator . The first time, I input 10 character as above example, click over textarea, validator checked and pass. After that, I click submit , send request to server, can not pass and reload page.

@michaloravec Just an example that I use max 10 character, but I used max 255 and more.So I need to use <text area>

@m7vm7v Let me try to custom. This is param send to Validator:

"text" => "'"abcd\r\n
	efghi
"'"

I tried to count by strlen

return strlen("abcd\r\nefghi"); // result is 11 character
MichalOravec's avatar
Level 75

@trungtranqn91 Use custom validation rules

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class MaxCharacters implements Rule
{
    protected $max;

    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct($max = 255)
    {
        $this->max = $max;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strlen(preg_replace('/\s+/', ' ', $value)) <= $this->max;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return "The :attribute may not be greater than {$this->max}.";
    }
}
use App\Rules\MaxCharacters;

$rules = [
    'text' => [new MaxCharacters(10)],
];
2 likes
trungtranqn91's avatar

@michaloravec

Thank for your solution . My custom validation is this way:


class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
       Validator::extend('max_custom', function ($attribute, $value, $parameters) {
            return strlen(str_replace(["\r\n", "\n", "\r"], ' ', $value)) <= $parameters[0];
        });
}


$rules = [
    'text' => 'max_custom:10',
];

It's work and shorter. Do you think should I do this way ?

MichalOravec's avatar

@trungtranqn91 It's up to you, I prefer to use Rule Objects

And for all whitespace using regex is better, because you have there tabs \t and so on.

preg_replace('/\s+/', ' ', $value)
1 like
trungtranqn91's avatar

@michaloravec I tested this but don't work,

$value = "abcd\r\nefghi";
return preg_replace('/\s+/', ' ', $value); // result: "abcd\r\nefghi" nothing happend , why?

Please or to participate in this conversation.