I have an array of integer like this $someVar = array(1,2,3,4,5). I need to validate $someVar to make sure every element is numeric.How can I do that?
I know that for the case of a single valued variable, the validation rule would be something like this $rules = array('someVar'=>'required|numeric'). How can I apply the same rule to every element of the array $someVar?
Thanks a lot for helping.
Now laravel has option to set condition on array elements. No need to write your own validator for simple things like validation int array. Use this (if using in controller)-
$validator = \Validator::make(compact('someVar'), [
'someVar' => 'required|array',
'someVar.*' => 'integer'
]);
$this->validateWith($validator);
or
$this->validate($request, [
'someVar' => 'array',
'someVar.*' => 'int'
]);
Validator::extend('numericarray', function($attribute, $value, $parameters)
{
foreach($value as $v) {
if(!is_int($v)) return false;
}
return true;
});
Use it
$rules = array('someVar'=>'required|array|numericarray')
Edit:
Up to date version of this validation would not require the definition of numericarray method.
$rules = [
'someVar' => 'required|array',
'someVar.*' => 'integer',
];
In Laravel 5 you can check the elements in an array by using .*. For you this would mean:
$rules = array('someVar' => 'required|array',
'someVar.*' => 'integer')
Start with adding a new validation attribute
Validator::extend('numeric_array', function($attribute, $values, $parameters)
{
if(! is_array($values)) {
return false;
}
foreach($values as $v) {
if(! is_numeric($v)) {
return false;
}
}
return true;
});
The function will return false if attribute is not an array or if one value is not a numeric value. Then add message to `app/lang/en/validation.php'
"numeric_array" => "The :attribute field should be an array of numeric values",
You can add custom rules for integer type value check of array
Just open file
/resources/lang/en/validation.php
Add the custom message before "accepted" message in the file.
'numericarray' => 'The :attribute must be numeric array value.',
"accepted" => "The :attribute must be accepted.",
Now Open the file
/app/Providers/AppServiceProvider.php
and then add the custom validation in boot function.
public function boot()
{
$this->app['validator']->extend('numericarray', function ($attribute, $value, $parameters)
{
foreach ($value as $v) {
if (!is_int($v)) {
return false;
}
}
return true;
});
}
Now you can use the numericarray for integer type value check of array
$this->validate($request, [
'field_name1' => 'required',
'field_name2' => 'numericarray'
]);
There is only the 'array' validation which ensures that the value is an array, but for your specific case you will have to create a custom filter:
Laravel 3: http://three.laravel.com/docs/validation#custom-validation-rules
Laravel 4: http://laravel.com/docs/validation#custom-validation-rules
AppServiceProvider.php
Validator::extend('integer_array', function($attribute, $value, $parameters)
{
return Assert::isIntegerArray($value);
});
Assert.php
/**
* Checks wheter value is integer array or not
* #param $value
* #return bool
*/
public static function isIntegerArray($value){
if(!is_array($value)){
return false;
}
foreach($value as $element){
if(!is_int($element)){
return false;
}
}
return true;
}
Related
How can I write rule for input field like below:
{!! Form::number("amount[]",null,['min' => 0, 'class' => 'form-control col-xs-2 ']) !!}
I tried following which gave error: htmlentities() expects parameter 1 to be string, array given
$rules = array(
'amount[]' => 'required'
);
$this->validate($request, $rules);
Update:
I tried this as suggested by a user, it's not redirecting it on page again. Below is controller method:
public function postEstimate(Request $request) {
$rules = array(
'amount' => 'required|array'
);
$this->validate($request, $rules);
}
I guess you got issues with what I explained so this is what I meant -
$rules = [];
$count_amounts = count($request->input('amount'));
foreach (range(0, $count_amounts) as $number) {
$rules['amount.' . $number] = 'required|integer|min:0';
}
This should check that each amount input you have is an integer and is bigger than 0 (like you defined in the html validation)
Instead try this:
private $rules = array(
'amount' => 'required|array',
);
public function postEstimate(Request $request) {
$this->validate($request, $this->rules);
}
or, try a validation with a 'amount' => 'required
im not sure about this 'amount' => 'required|array
For custom rules implementation of integer type value check of an array
firstly open the following file
/resources/lang/en/validation.php
Then add the custom message
'numericarray' => 'The :attribute must be numeric array value.',
'requiredarray' => 'The :attribute must required all element.',
Again open the another file
/app/Providers/AppServiceProvider.php
Now add custom validation code in the boot function.
public function boot()
{
$this->app['validator']->extend('numericarray', function ($attribute, $value, $parameters)
{
foreach ($value as $v) {
if (!is_int($v)) {
return false;
}
}
return true;
});
$this->app['validator']->extend('requiredarray', function ($attribute, $value, $parameters)
{
foreach ($value as $v) {
if(empty($v)){
return false;
}
}
return true;
});
}
Now you can use the requiredarray for all element required of array. And also use the numericarray for integer type value check of array
$this->validate($request, [
'field_name1' => 'requiredarray',
'field_name2' => 'numericarray'
]);
if you expect amount as an array the rules should be
$rules = array(
'amount' => 'required|array'
);
check the doc
If your not redirecting or getting a validation error means there is no validation error
just dd($request->input('amount')) in the controller and check its a array or not if it's a array then validations will pass.
I have the following request class:
<?php namespace App\Http\Requests\User;
use App\Http\Requests\Request;
use Validator;
use Session;
use Auth;
use App\User;
class RegisterStep1Request extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Set up the validation rules
*/
public function rules()
{
Validator::extend('valid_date', function($attribute, $value, $parameters)
{
$pieces = explode('/', $value);
if(strpos($value, '/')===FALSE) {
return false;
} else {
if(checkdate($pieces[1], $pieces[0], $pieces[2])) {
return true;
} else {
return false;
}
}
});
return [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email|unique:users,email',
'dob' => 'required|regex:/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/|valid_date',
'mobile' => 'required',
'password' => 'required|confirmed'
];
}
public function messages()
{
return [
'first_name.required' => 'The first name field is required.',
'last_name.required' => 'The last name field is required.',
'email.required' => 'The email address field is required.',
'email.email' => 'The email address specified is not a valid email address.',
'email.unique' => 'The email address is already registered with this website.',
'dob.required' => 'The date of birth field is required.',
'dob.regex' => 'The date of birth is invalid. Please use the following format: DD/MM/YYYY.',
'dob.valid_date' => 'The date of birth is invalid. Please check and try again.',
'mobile.required' => 'The mobile number field is required.',
'password.required' => 'The password field is required.',
'password.confirmed' => 'The confirm password field does not match the password field.'
];
}
}
I want to add the following sometimes rule:
Validator::sometimes('dob', 'valid_date', function($input)
{
return apply_regex($input->dob) === true;
});
How would I add this to my request class?
I have amended my rules method to the following:
public function rules()
{
Validator::extend('valid_date', function($attribute, $value, $parameters)
{
$pieces = explode('/', $value);
if(strpos($value, '/')===FALSE) {
return false;
} else {
if(checkdate($pieces[1], $pieces[0], $pieces[2])) {
return true;
} else {
return false;
}
}
});
Validator::sometimes('dob', 'valid_date', function($input)
{
return apply_regex($input->dob) === true;
});
return [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email|unique:users,email',
'dob' => 'sometimes|required|regex:/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/|valid_date',
'mobile' => 'required',
'password' => 'required|confirmed'
];
}
But I now get the following error when I submit the form:
FatalErrorException in Facade.php line 216:
Call to undefined method Illuminate\Validation\Factory::sometimes()
There is a documented way to make changes to the request's validator instance in Laravel 5.4. You should implement the withValidator method for that.
Based on the example from #lukasgeiter's answer, you may add the following to your request class:
/**
* Configure the validator instance.
*
* #param \Illuminate\Validation\Validator $validator
* #return void
*/
public function withValidator($validator)
{
$validator->sometimes('dob', 'valid_date', function ($input) {
return apply_regex($input->dob) === true;
});
}
By doing this you don't have to worry about overriding internal methods. Besides, this seems to be the official way for configuring the validator.
You can attach a sometimes() rule by overriding the getValidatorInstance() function in your form request:
protected function getValidatorInstance(){
$validator = parent::getValidatorInstance();
$validator->sometimes('dob', 'valid_date', function($input)
{
return apply_regex($input->dob) === true;
});
return $validator;
}
You just need to add the dob key to the array you are returning, along with the validation ruleset to follow, including sometimes.
In this case:
'dob' : 'sometimes|required|regex:/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/|valid_date'
According to your comment
I want the rule valid_date to only run if the regex rule returns true. Otherwise
the valid_date rule errors if the date isnt in the right format.
Validator::extend('valid_date', function($attribute, $value, $parameters)
{
\\use the regex here instead
if (!preg_match('/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/', $value)) return false;
$pieces = explode('/', $value);
if(strpos($value, '/')===FALSE) {
return false;
} else {
if(checkdate($pieces[1], $pieces[0], $pieces[2])) {
return true;
} else {
return false;
}
}
});
$validator = Validator::make($data, [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email|unique:users,email',
'dob' => 'required|valid_date',
'mobile' => 'required',
'password' => 'required|confirmed'
]);
I have a form with 5 multiple-choice dropdown lists. When submitted, I am trying to run some validation to check that at least one item has been checked.
The code in my controller;
$input = Request::except('postcode_id'); //all user input from the form
$validator = \Validator::make(
[
$input => 'required'
]
);
if ($validator->fails())
{
print "failed";
}else{
print "passed";
}
The error I get is; Illegal offset type. I think I might need to do a custom validator but would like to check first in case there is an easier way.
The first argument of Validator::make() is the data, and the second is an array of validation rules, which are indexed by the input names. You can use required_without_all to validate that at least one must be present, but it is a little verbose:
$validator = \Validator::make($input, [
'dropdown_1' => 'required_without_all:dropdown_2,dropdown_3,dropdown_4,dropdown_5'
'dropdown_2' => 'required_without_all:dropdown_1,dropdown_3,dropdown_4,dropdown_5'
'dropdown_3' => 'required_without_all:dropdown_1,dropdown_2,dropdown_4,dropdown_5'
'dropdown_4' => 'required_without_all:dropdown_1,dropdown_2,dropdown_4,dropdown_5'
'dropdown_5' => 'required_without_all:dropdown_1,dropdown_2,dropdown_3,dropdown_4'
]);
Or write some code to generate the $rules array:
$fields = ['dropdown_1', 'dropdown_2', 'dropdown_3', 'dropdown_4', 'dropdown_5'];
$rules = [];
foreach ($fields as $i => $field) {
$rules[$field] = 'required_without_all:' . implode(',', array_except($fields, $i));
}
$validator = \Validator::make($input, $rules);
You need to use strings in your validator, not variables. Try this instead.
$validator = \Validator::make(
[
'input' => 'required'
]
);
Custom validator itself is not too difficult. I am using it all the time for array input validation. In Laravel 5 Request I will do something like that
public function __construct() {
Validator::extend("pcc", function($attribute, $value, $parameters) {
$rules = [
'container_id' => 'exists:containers,id'
];
foreach ($value as $containerId) {
$data = [
'container_id' => $containerId
];
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
return false;
}
}
return true;
});
}
public function rules() {
return [
'containers' => 'required|pcc',
];
}
I have done all the things for the validation for the variable in laravel but for emails I got one simple problem.
From doc of Laravel,
'email' => 'required|email'
I got to know this is for only one email address but for like,
email=abc#xyz.com,xyz#abc.com, def#ghi,com
When I send array of the email i still get email is not a valid email.
I have done more like,
'email' => 'required|email|array'
But I still got error. can any body help.
Thanks,
You need to write custom Validator, which will take the array and validate each ofthe emails in array manually. In Laravel 5 Request you can do something like that
public function __construct() {
Validator::extend("emails", function($attribute, $value, $parameters) {
$rules = [
'email' => 'required|email',
];
foreach ($value as $email) {
$data = [
'email' => $email
];
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
return false;
}
}
return true;
});
}
public function rules() {
return [
'email' => 'required|emails'
];
}
In 5.6 or above you can define your validator rule as follows:
'email.*' => 'required|email'
This will expect the email key to be an array of valid email addresses.
We can achieve this without custom validation,We can overridden a method prepareForValidation
protected function prepareForValidation()
{
//Here email we are reciving as comma seperated so we make it array
$this->merge(['email' => explode(',', rtrim($this->email, ','))]);
}
Then above function will call automatically and convert email-ids to array, after that use array validation rule
public function rules()
{
return [
'email.*' => 'required|email'
];
}
Laravel 5.2 introduced array validation and you can easily validate array of emails :)
All you need is exploding the string to array.
https://laravel.com/docs/5.2/validation#validating-arrays
I did it like this. Working good for me.
if email or emails (email1#gmail.com, email2#yahoo.com, email3#gmail.com) are coming from a Form like this following custom validator works. This need to be added to - AppServiceProvider.php - file. And new rule is - 'emails'.
/**
* emails
* Note: this validates multiple emails in coma separated string.
*/
Validator::extend('emails', function ($attribute, $value, $parameters, $validator) {
$emails = explode(",", $value);
foreach ($emails as $k => $v) {
if (isset($v) && $v !== "") {
$temp_email = trim($v);
if (!filter_var($temp_email, FILTER_VALIDATE_EMAIL)) {
return false;
}
}
}
return true;
}, 'Error message - email is not in right format');
And in your controller, it can be used like this:
$this->validate($request, [
'email_txt_area' => 'emails',
]);
If you don't want to override prepareForValidation just because of one rule here's another approach using closures:
$rules = [
'name' => 'required|string|max:255',
'email' => [
'required',
function ($attribute, $value, $fail) {
$emails = array_map('trim', explode(',', $value));
$validator = Validator::make(['emails' => $emails], ['emails.*' => 'required|email']);
if ($validator->fails()) {
$fail('All email addresses must be valid.');
}
},
],
];
Tested with Laravel 9.x
I'm trying laravel required validator in my code, unfortunately it fails for even empty string. I do not want it fail for empty string.
$validator = \Validator::make(array("name"=>""), array("name"=>"required"));
if ($validator->fails()){
var_dump($validator->messages());
} else {
die("no errors :)");
}
It gives me the following output
object(Illuminate\Support\MessageBag)[602]
protected 'messages' =>
array (size=1)
'name' =>
array (size=1)
0 => string 'The name field is required.' (length=27)
protected 'format' => string ':message' (length=8)
It is supposed to pass, since i'm giving an empty string as the name field.
The above behavior happens in OSX environment (PHP Version 5.5.18), but it works fine in linux environment (PHP Version 5.5.9-1ubuntu4.5).
The required rule actually returns false if you pass an empty string.
If we look at the code (Illuminate\Validation\Validator)
protected function validateRequired($attribute, $value)
{
if (is_null($value))
{
return false;
}
elseif (is_string($value) && trim($value) === '')
{
return false;
}
// [...]
return true;
}
I think your only option here is to write your own validation rule that checks if the value is not null:
Validator::extendImplicit('attribute_exists', function($attribute, $value, $parameters){
return ! is_null($value);
});
(The extendImplicit is needed because with extend custom rules will only run when the value is not an empty string)
And then use it like this:
\Validator::make(array("name"=>""), array("name"=>"attribute_exists"));
I use this:
'my_field' => 'present'
In Laravel 5.6 you can use just this:
public function rules()
{
return [
'my_field' => 'required|string|nullable'
];
}
Might work on older versions as well, I only tried on 5.6
i have developed my own way to process optional input. i use associative array for validation.
$rules = array('sltcategoryid' => 'required',
'txttitle' => 'required|min:10|max:255',
'txtdetail' => 'required|min:10|max:255',
'rdocontenttype' => 'required',
'rdoislive' => 'required');
if($request->rdocontenttype=="1" || $request->rdocontenttype=="2" && trim($request->txtcontent)=="")
$rules["txtcontent"]="required|min:10|max:2048";
else if ($request->rdocontenttype=="3" && isset($request->fildata)==false)
$rules["fildata"] ="required|mimes:png,jpg,jpeg,pdf,doc,xls,ppt,bmp,zip";
$validator = Validator::make($request->all(),$rules);
if ($validator->fails())
return redirect('content/create')->withErrors($validator)->withInput();
else
return back()->with("message","content processed successfully");