Laravel email validation issue - laravel

Default Laravel Validation class allows strange emails. Here is the Validation rules that I defined:
return Validation::make($data, [
'email' => 'required|string|email|max:100|unique:customers,email'
]);
When I tried to use some strange email like:
aaaa?#%&'#şğüçi̇ö.com it passes the validation. However the non latin characters on the email is converted before DB insert. So the email address on the database doesn't match with the original one.
In order to prevent this I want to disallow the usage of non-latin characters after the # symbol. I tried the custom rule which is:
public function passes($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_EMAIL)
&& preg_match('/#.+\./', $value);
}
but it is not working. It would be good to get some help on this.
Edit 1
Thanks for your responses! But apparently the reason that the custom validator not taking action is that Laravel sanitizes all input data before any manipulation. That's why after it converts the non-latin characters, preg_replace() returns 1 all the time since there is no non-latin characters on the input. First of all I need to find a solution to this and prevent Laravel to sanitize the input.

From your question I understand you already created a custom Validation Rule and use it like
...
'email' => [
'required',
'string',
...
new ValidateLatinEmail()
]
As you can see here, your RegEx is the problem with that validation
This one should work:
public function passes($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_EMAIL)
&& preg_match('/#[\x00-\x7F]*\./', $value);
}

Related

Laravel custom validation: only validate input if input given

So I followed this tutorial to learn how to upload images with Laravel using Vue: Image upload and validation using Laravel and VueJs
Everything works fine, but I want to make the image upload optional. Now the custom validation fails for the AppServiceProvider. if it does not have any input then i get this error
trying to access an attribute inside an array that does not exist. Undefined offset: 1
I could avoid the error by asking
if (request('image'))
In the controller and applying the validation for the other fields only if no image is given. However, this gets incredibly messy.
So I am looking for a way to get the custom validation rule working if there is no input. Or is that the wrong way?
Here is the custom validation rule:
public function boot()
{
Validator::extend('image64', function ($attribute, $value, $parameters, $validator) {
$type = explode('/', explode(':', substr($value, 0, strpos($value, ';')))[1])[1];
if (in_array($type, $parameters)) {
return true;
}
return false;
});
Validator::replacer('image64', function($message, $attribute, $rule, $parameters) {
return str_replace(':values',join(",",$parameters),$message);
});
}
In some situations, you may wish to run validation checks against a field only if that field is present in the input array. To quickly accomplish this, add the sometimes rule to your rule list:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
In the example above, the email field will only be validated if it is present in the $data array.
Reference: Conditionally Adding Rules
Laravel provides a validation called 'nullable' in case other validation rules should not be run if the given value is null: A Note On Optional Fields

Laravel 5: Validating Edits In-Place

I had previously asked a question here in regards for setting up in-place editing with Laravel 5 and AJAX. I hadn't updated it because I had managed offline to figure out what was wrong with it.
While the table is capable of editing user rows in-place, I'm now trying to add validation on top of it, intending on utilizing Laravel's built-in validator. However, for some reason it doesn't seem to be working. When I try to pass in the failed validator back through the JSON, it spits out every possible error I'm checking for. It's as if the validator is treating every input as empty, which doesn't make sense, as the rest of the function is clearly taking in the inputs as intended.
The code snippets in my previous question are still mostly relevant, but there have been updates to HomeController.php, as can be seen below:
public function updateTable(Users $users){
$user = request()->input('user');
$first_name = request()->input('first_name');
$last_name = request()->input('last_name');
$validator = Validator::make(request()->all(), [
'firstName' => 'required|alpha',
'lastName' => 'required|alpha'
], [
'firstName.required' => 'You need to give a first name!',
'firstName.alpha' => 'A first name can only contain letters!',
'lastName.required' => 'You need to give a last name!',
'lastName.alpha' => 'A last name can only contain letters!'
]);
if ($validator->fails()) {
return response()->json($validator, 404);
}
$employees->editUser($user, $first_name, $last_name);
return response()->json($user);
}
So I realized the issue was twofold. First, what I was trying to return when the validator failed was incorrect. Rather than simply passing the whole validator, I needed to simply pass its messages, like so:
if ($validator->fails()) {
return response()->json($validator->messages(), 404);
}
The second issue actually had to do with calling "request()->all()". I had assumed the array obtained would have worked, but for some reason it didn't. When I created a new array based on the values in "request()" it was able to get the validator results I was expecting.

Yii2 compare email without case sensitive

I use the simple compare validation rule offered by Yii2 like this:
[confirm_email', 'compare', 'compareAttribute'=>'email', 'message'=>"Emails don't match"],
The problem is that this rule compares two emails 100% including Case Sensitive which means email#test.com and email#Test.com will generate validation error.
Is there a way to remove this Case Sensitive comparison from this rule?
strcasecmp does not handle multibyte characters, read this
suggestion is to use strtolower()
you might also be interested in yii's input filter, to transform input to lowercase, like this:
[
// both email fields tolower
[['email', 'confirm_email'], 'filter', 'filter' => 'strtolower'],
// normalize "phone" input
['phone', 'filter', 'filter' => function ($value) {
// normalize phone input here
return $value;
}], ]
You can create custom validation if you want.
public function rules()
{
return [
// an inline validator defined as the model method validateEmail()
['email', 'validateEmail'],
];
}
public function validateEmail($attribute, $params)
{
if (strcasecmp($this->attribute, $this->confirm_email) == 0) {
$this->addError($attribute, 'Username should only contain alphabets');
}
}
It will compare emails with binary safe case-insensitive.

How can I validate input does not contain specific words?

In my signup form I have a nickname field that users can enter text in to identify themselves on my site. In the past some users have entered nicknames which others might find offensive. Laravel provides validation functionality for forms, but how can I ensure that a form field doesn't contain words users might find offensive?
Whilst Laravel has a wide range of validations rules included, checking for the presence of a word from a given list isn't one of them:
http://laravel.com/docs/validation#available-validation-rules
However, Laravel also allows us to create our own custom validation rules:
http://laravel.com/docs/validation#custom-validation-rules
We can create validation rules using Validator::extend():
Validator::extend('not_contains', function($attribute, $value, $parameters)
{
// Banned words
$words = array('a***', 'f***', 's***');
foreach ($words as $word)
{
if (stripos($value, $word) !== false) return false;
}
return true;
});
The code above defines a validation rule called not_contains - it looks for presence of each word in $words in the fields value and returns false if any are found. Otherwise it returns true to indicate the validation passed.
We can then use our rule as normal:
$rules = array(
'nickname' => 'required|not_contains',
);
$messages = array(
'not_contains' => 'The :attribute must not contain banned words',
);
$validator = Validator::make(Input::all(), $rules, $messages);
if ($validator->fails())
{
return Redirect::to('register')->withErrors($validator);
}
In Laravel 5.7 and possibly earlier versions, you could use the built in not_regex rule to check for some strings. Like this for example, within a controller using the validate method. Validate form input that expects a name for a dog. :
...
public function update(Request $request) {
$custom_validation_messages = [
'not_regex' => "C'mon! Be original. Give your dog a more interesting name!"
];
$this->validate($request, [
'pet_name' => [ 'not_regex:/^(fido|max|bingo)$/i' ],
], $custom_validation_messages);
...
}
In this case if the submitted 'pet_name' value is:
fido
FIDO
MaX
MAx
BinGO
bingo
etc.
Then validation will fail.
For the inverse of this, i.e. you only want Fido, Max or Bingo then you could use the regex rule like so:
[ 'regex:/^(fido|max|bingo)$/i' ]
See Laravel Validation (not regex).

Check if field exists in Input during validation using Laravel

I want to make sure that certain fields are posted as part of the form but I don;t mind if some are empty values.
The 'required' validation rule won't work as I am happy to accept empty strings. I have tried the below, but as the 'address2' field is never sent, the validator doesn't process it.
Any ideas?
$rules = array(
'address2' => 'attribute_exists'
);
class CustomValidator extends Illuminate\Validation\Validator {
public function validateAttributeExists($attribute, $value, $parameters)
{
return isset($this->data[$attribute]);
}
}
You can use Input::has('address2') to check if something is posted by address2 input name. See the example:
if(Input::has('address2')) {
// Do something!
}
In Laravel 5,
if($request->has('address2')){
// do stuff
}
You should make custom validator like this.
use Symfony\Component\Translation\TranslatorInterface;
class CustomValidator extends Illuminate\Validation\Validator {
public function __construct(TranslatorInterface $translator, $data, $rules, $messages = array())
{
parent::__construct($translator, $data, $rules, $messages);
$this->implicitRules[] = 'AttributeExists';
}
public function validateAttributeExists($attribute, $value, $parameters)
{
return isset($this->data[$attribute]);
}
}
This will make AttributeExists work without to use require. For more explain about this. When you want to create new validator rule. If you don't set it in $implicitRules, that method will not work out if you don't use require rule before it. You can find more info in laravel source code.
When you submit a form each and every field is posted, matter of fact is if you leave some filed empty then that field value is null or empty. Just check the POST parameters once, to do so open the firebug console in firefox and submit the form, then check the post parameters. As you want to accept empty string what is the use of any rule?
else You can do this
$addr2=Input::get('address2');
if(isset($addr2)){
//do here whatever you want
}else{
//do something else
$addr2='';//empty string
}
Actually, Laravel has a method to validate if an attribute exists even if not filled.
$rules = [
'something' => 'present'
];
All the validation rules are stored in Validator class (/vendor/laravel/framework/src/Illuminate/Validation/Validator.php), you can check for the implementation of each rule, even no documented rules.

Resources