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");
Related
I'm trying to create a validator that require at least one of three input.
I tried this
protected function validateFundingSource (): array
{
return request()->validate([
'title' => 'required',
'description' => 'required',
'national' => 'nullable',
'province' => Rule::requiredIf(!request('national')),
'url' => [
'required_without_all:phone,email',
'active_url'
],
'phone' => [
'required_without_all:url,email|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im'
],
'email' => [
'required_without_all:url,phone|email:rfc,dns'
],
'categories' => 'exists:categories,id'
]);
}
But it was was forcing only the first field (url). So I tried with Complex Conditional Validation.
protected function validateFundingSource ()
{
$v = Validator::make(request()->all(), [
'title' => 'required',
'description' => 'required',
'national' => 'nullable',
'categories' => 'exists:categories,id',
]);
$v->sometimes('province', 'required', function ($input) {
return ($input->national === null) ;
});
$v->sometimes('url', 'required|active_url', function ($input) {
return (($input->phone === null) && ($input->email === null));
});
$v->sometimes('phone', 'required|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im', function ($input) {
return (($input->url === null) && ($input->email === null));
});
$v->sometimes('email', 'required|email:rfc,dns', function ($input) {
return (($input->url === null) && ($input->phone === null));
});
return $v;
}
But still no luck... Now it's never required I can submit all three empty field and it's working...
Any clues to help me please ?
Thank you !
You code is working fine. you just forget to check if validate pass or not.
because when you use Validator::make you need to manually check it. for request()->validate laravel will do it for you. inside your validateFundingSource () function just check it pass validate or not before return like this:
private function validateFundingSource () {
$v = Validator::make(request()->all(), [
'title' => 'required',
'description' => 'required',
'national' => 'nullable',
'categories' => 'exists:categories,id',
]);
$v->sometimes('province', 'required', function ($input) {
return ($input->national === null) ;
});
$v->sometimes('url', 'required|active_url', function ($input) {
return (($input->phone === null) && ($input->email === null));
});
$v->sometimes('phone', 'required|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im', function ($input) {
return (($input->url === null) && ($input->email === null));
});
$v->sometimes('email', 'required|email:rfc,dns', function ($input) {
return (($input->url === null) && ($input->phone === null));
});
// check if validae failed
if($v->fails()) {
dd('fail', $v); // do something when it failed
}
}
also sorry for my bad English & hope it help
If you're looking for "at least one of" url, phone, or email then you want to use required_without. This rule means the field is required when any of the specified fields are missing; required_without_all means it's required when all of the specified fields are missing.
You are also confusing rule syntax, you must use either array or pipe-delimited string syntax, not both at once.
You may want to improve your phone number regex as well; + -. (000-111.9999 #8 is not a great phone number, but would pass your validation. I'd suggest sanitizing your value to remove everything except digits and a leading +, then using a better pattern on what's left.
And, it's just a cosmetic change but you can replace Rule::requiredIf(!request('national')), with a simple required_if rule like the others.
Changing to a form request validation, this would look like:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreFundingsource extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Prepare the data for validation.
*
* #return void
*/
protected function prepareForValidation()
{
$phone = preg_replace("/[^0-9]/", "", $this->phone);
if (strpos($this->phone, "+") === 0) {
$phone = "+$phone";
}
$this->merge(["phone"=>$phone]);
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => ['required'],
'description' => ['required'],
'national' => ['nullable'],
'province' => ['required_if,national,'],
'categories' => ['exists:categories,id']
'url' => [
'required_without:phone,email',
'active_url'
],
'phone' => [
'required_without:url,email',
'regex:/^\+?1?[2-9][0-9]{5,14}$/'
],
'email' => [
'required_without:url,phone',
'email:rfc,dns'
],
];
}
}
Is there any way to validate required field when the requested url contains some parameter?
Assuming you are using Form requsts, you can simple use PHP condition.
public function rules()
{
$rules = []; // here you put some rules
// here you check condition and add some rule when it's true
if (str_contains($this->input('url'), 'something')) {
$rules['some_other_field'] = 'required';
}
return $rules;
}
You need to first check the route before validating....
$roles =[
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
];
if(Route::getCurrentRoute()->getPath() == "xxxxx"){
$role['desc'] = 'required'
}
if(\Request::route()->getName() == "yyyy"){
$role['desc'] = 'required'
}
if($request->is('admin/*')){
$role['desc'] = 'required'
}
$this->validate($request, $role);
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 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 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;
}