Laravel custom validation issue - php

I am trying to register a custom validation rule but it does not seem to work. I need either of 2 fields to be filled in. One is a URL(link) field and other is a File input(file_upload).
Here is my custom validation:
Validator::register('file_check', function($attribute, $value, $parameters) {
if (!trim($value) == "" || array_get(Input::file($parameters[0]), 'tmp_name')) {
return true;
}
return false;
});
$messages = array(
'file_check' => 'Please upload a file or provide a link to files.',
);
$rules = array(
'link' => 'url|file_check:file_upload',
'file_upload' => 'mimes:jpg,jpeg,gif,png,psd,ai,bmp,xls,xlsx,doc,docx,zip,rar,7z,txt,pdf'
);
$validation = Validator::make(Input::all(), $rules, $messages);
if ($validation - > fails()) {
return Redirect::to('page') - > with_errors($validation - > errors) - > with_input();
}
Need help :)
EDITED
Also, I just noticed that the validation rule should accept "PSD" files but when I try to upload a PSD file it redirects with the error "Invalid file type".

I am maybe late in party but may be somebody will find it useful, in case you need to create implicit rule which will be called even if field is not present in Input (like required,required_if....) use
Validator::extendImplicit( 'validator_name', function($attribute, $value, $parameters)
{
});
Check this out

I was just struggling with this myself! It turns out that except when a few specific rules are applied to them, Laravel doesn't pass empty fields through the Validator at all. So a custom either-this-or-that rule can't work, since at least one of the two fields is likely to not be visible to it.
You can get around this by moving from the registering-a-new-rule approach to the alternate extend-the-Validator-class approach. Your new class will inherit all the methods of the standard Validator, including a method called "implicit" (you can find the original on line 215 of the standard Validator class), which specifies a whitelist of rules that Laravel should pass fields along to even if they are empty. Add your new rule to that list and you should be good to go.

Jason is right, but there is one thing that can be confusing.
Laravel's 'registering a new rule' approach uses the syntax 'Validator::extend(...'. As described elsewhere, this is convenient when you want to customize in a special situation. However, if you want to add a number of reusable rules, then you probably want to use the extend-the-Validator-class approach. In that case, IF you have a rule conditionally requires something, you need to override the existing implicitRules array with a new one adding your rule.
If the first rules you add don't conditionally require, you will think you have it nailed, then you will spend hours trying to figure out why your new 'RequireWhenBlaBla...' rule is invisible.

Related

Laravel Validation: Custom rules on arrays (before_if)

I am trying to write a custom before_if rule that mirrors the required_if rule. What I am trying to accomplish is making sure that the "primary" name on an account is not a minor (18+ years), but I am not quiet sure how to deal with this because I am looking at an array.
My rule looks like this
'names.*.birthdate' => 'required|date|before_if:-18 years,names.*.type,0' // Type 0 is primary name
However, I am not quite sure what to do in my extend logic. Specifically, I am not sure how to find the index of the current name I am on. I know this is possible because I already do this multiple times using required_if.
Validator::extend('before_if', function($attribute, $value, $parameters, $validator){
// Not sure how to find the current index
});

How can I require all fields matching a regular expression with laravel?

I am making an application where users can upload questions, and questions can have multiple correct answers. The correct answers have names of the form correctAnswer1 correctAnswer2 etc.
I want to know how to require all submitted fields matching this pattern; I was thinking of using something analogous to
/correctAnswer[0-9]/ => 'required'
I'm not sure of the logic behind your requirement, kinda seems you should do things in a different manner, but again I do not know how your app works so I can't be a judge of that. So if the user can add new correct answers fields on the form, and you wan't them to not be empty it makes some sense.
You can't have a regex in the rule name but you can do the following:
$rules = [
// your other rules
];
$correctAnswers = preg_grep( '/^correctAnswer[1-9]{1}$/', array_keys($this->all()));
// use $this->all() when in Http\Requests\YourRequest
// if you are not using the request method of validation (you validate in controller)
// simply replace $this->all() with $request->all() or Input::all().
foreach ($correctAnswers as $correctAnswer) {
$rules[$correctAnswer] = 'required';
}
return $rules;
This assumes you are using the Laravel 5, Http\Requests to validate your input. If you are doin'g the validation elsewhere (in controller for example), just replace $this->all() with $request->all() or Input::all(). I can't give the exact choice as I do not know exactly how you do the validation and what version of laravel you use.
PS: This will match only correctAnswer1 to correctAnswer9. If you want more just play with the [0-9]{1} part of the regex.

Is there a validation rule for "not present"?

I need to check if the key is not set in the array using Laravel validator.
That would be the complete opposite of the "required" validation rule.
Basically the array will be passed to update method if it passes the validation and I want to make sure one column will not be updated.
Is there a way to check if the value "is not present"?
Thank you
EDIT:
I'm currently using Laravel 5
EDIT:
I managed to write my own validation rule by calling Validator::extendImplicit. However I get $value as null to my validation function both when I set it to null or when I don't set it at all. Is there a way to check if the value is set?
I believe I found a solution:
$validator->extendImplicit('not_present', function($attribute, $value, $parameters)
{
return !array_key_exists($attribute, $this->data);
});
I'm not calling extendImplicit statically because the Validator class object is injected to the controller of my class.
I need to access $this->data ($this referring to the Validator object) to make sure the key doesn't exist in the array being validated.
Based on the #MaGnetas answer I came up with this 2 rules that can be applied on any model.
I'm using Laravel 5.4 so putting this lines on your AppServiceProvider.php should work.
The first approach (extendImplicit and array_key_exists)
Validator::extendImplicit('not_present', function($attribute, $value, $parameters, $validator)
{
return !array_key_exists($attribute, $validator->getData());
});
Ussing $validator->getData() we could use the Validator statically.
The second approach (extend and false)
Validator::extend('not_present', function($attribute, $value, $parameters, $validator)
{
return false;
});
You could use extend because we don't need the rule to be executed if the data has not the property (because that's exactly what we want right?)
On the docs:
By default, when an attribute being validated is not present or contains an empty value as defined by the required rule, normal validation rules, including custom extensions, are not run. more info
Important: The only difference is that using extend, empty strings will not run the validation. But if you have setting TrimStrings and ConvertEmptyStringsToNull on your middleware (which AFAIK is the default option) there will be no problem
No there is no build in validtion rule for this, but you can create your own validation rule.
The simplest way to do this:
Validator::extend('foo', function($attribute, $value, $parameters)
{
// Do some stuff
});
And check if key exists.
More information:
http://laravel.com/docs/4.2/validation#custom-validation-rules
For people looking for the not_present logic in 7.x apps (applicable for all versions), remember that you can simply use the validated data array for the same results.
$validatedKeys = $request->validate([
'sort' => 'integer',
'status' => 'in:active,inactive,archived',
]);
// Only update with keys that has been validated.
$model->update(collect($request->all())->only($validatedKeys)->all());
my model has more attributes but only these two should be updatable, therefore I too were looking for an not_present rule but ending up doing this as the results and conceptual logic is the very same. Just from another perspective.
I know this question is really old but you can also use
'email' => 'sometimes|required|not_regex:/^/i',
If the email is present in the request, the regex will match any characters in the request and if the email is an empty string but is present in request the sometimes|required will catch that.

Laravel Form Validation, fail if not empty

I have an input field which needs to be empty, otherwise I want the validation to fail. This is an attempt at stopping spam through a contact form.
I've looked at the documentation for the validation but there's nothing to do this, other than the "max" rule, but this doesn't work.
Any other options?
Here's a clean and (probably) bullet-proof solution:
'mustBeEmpty' => 'present|max:0',
In the method where you are validation, extend/add custom rule:
Validator::extend('mustBeEmpty', function($attr, $value, $params){
if(!empty($attr)) return false;
return true;
});
Then you may use this rule like:
protected $rules = array(
'emptyInputField' => 'mustBeEmpty'
);
Then everything is as usual, just use:
$v = Validator::make(Input::except('_token'), $rules);
if($v->passes()) {
// Passed, means that the emptyInputField is empty
}
There are other ways to do it without extending it like this or extending the Validator class but it's an easy Laravelish way to do it. Btw, there is a package available on Github as Honeypot spam prevention for Laravel applications, you may check that.
For Laravel 8.x and above, you may use the prohibited validation rule:
return [
'emptyInputField' => 'prohibited',
];
In laravel 5.8 you can use sometimes for conditional rules adding. 'email' => 'sometimes|email' . This rules will be applied if there is something present in input field.
You can use the empty rule. Details can be seen here: https://laravel.com/docs/5.2/validation#conditionally-adding-rules

Laravel - Custom validation for file doesn't work

I am trying to use custom validation rules for file inputs in Laravel. The file input name is "photo". I am trying to apply a rule called "validate_art", to this file input. I know there's "image" validation rule, but I want to apply my own customized rule to this file input.
Here's the code :
$rules = array('name'=>'required|unique:user,name','startyear'=>'numeric','endyear'=>'numeric'
,'photo'=>'validate_art');
Validator::extend('validate_art',function($attribute,$value,$parameters){
// returning false just for testing purpose
return false;
});
What happens is, it doesn't apply the rule to the field at all. When I try to use this rule to some other field for testing purposes, it works without failure. Am I doing something wrong? Or custom validation cannot be applied for file inputs? Please someone, throw some light at this. I would really appreciate that.
first you should modify your input data
foreach ($inputs as $k=>$input){
if($input instanceOf \Symfony\Component\HttpFoundation\File\UploadedFile)
$inputs[$k]=$_FILES[$k];
}
then send $input to validator $validator=Validator::make($input,$rules)

Categories