Laravel - custom validation - laravel

I have this validation:
$data = request()->validate([
'qty100' => ['integer'],
'qty250' => ['integer'],
'qty500' => ['integer'],
]);
I would need to check if at least one of them is bigger than 0... how can this be done?

I think there is no built-in validation rule does something like what you want in Laravel, so you'll need to implement a custom validator, that will let you reuse validation where needed.
this is one way of doing it.
request()->validate([
'intone' => ['required', 'integer', 'greaterThanZeroWithoutAll:inttwo,intthree'],
'inttwo' => ['required', 'integer'],
'intthree' => ['required', 'integer'],
]);
in your AppServiceProvider
public function boot()
{
//here we are creating a custom rule. called 'greaterThanZeroWithoutAll'
//$attribute is the name we are validating,
//$value is the value we get from the request,
//$parameters are the arguments we pass in like greaterThanZeroWithoutAll:inttwo,intthree inttwo and intthree are parameters
//$validator is the validator object.
Validator::extend('greaterThanZeroWithoutAll', function ($attribute, $value, $parameters, $validator) {
//$validator->getData() is all the key value pairs from greaterThanZeroWithoutAll rule.
//array_values($validator->getData()) we are only interested in the values, so this will return all the values.
//implode(array_values($validator->getData())) will turn it into string
//!(int) implode(array_values($validator->getData())) this uses no glue when imploding, then explicitly casts the generated string as an integer, then uses negation to evaluate 0 as true and non-zero as false. (Ordinarily, 0 evaluates as false and all other values evaluate to true.)
if (!(int) implode(array_values($validator->getData()))) {
//means all values are 0
return false;
}
return true;
});
// this is error message
Validator::replacer('greaterThanZeroWithoutAll', function ($message, $attribute, $rule, $parameters) {
return 'not all fields are greater 0';
});
}
!(int) implode(array_values($validator->getData())) this code basically checks all the values are zero, there should many other ways to do this.
The reason we only do on the first value is that, we pass the other two values in and compare with it. So, it does it.

Related

Use `trans_choice()` in request validation messages with validation rule parameter

I need a request validation rule to return a custom message upon failure, and since the field being validating is an array with a min:x rule i'd like to have a custom message for both singular and plural variations.
I'm just wondering how to pass to the trans_choice() function the :min parameter from the validation rule:
Translation file:
'array' => [
'field' => [
'min' => 'You need to select at least one item.|you need to select at least :min items',
],
],
Request message() method:
public function messages() {
'my.array.field.min' => trans_choice('translations::array.field.min', ???),
}
It seems like there's nothing built into Laravel to use trans_choice whenever you can pluralise a translation string.
A way you could solve that is by temporarily (or permanently, whatever fits your use-case) changing the replacer for the min rule to something like this:
Validator::replacer('min', function ($message, $attribute, $rule, $parameters, $validator) {
$minValue = $parameters[0];
$message = Str::contains($message, '|')
? trans_choice($message, $minValue)
: $message;
return str_replace(':min', $minValue, $message);
});
Or by extending the Validator factory to work in your favour, but since that requires you to change many of it's methods I don't really recommend that.

Opposite of required_if in laravel using multiple value evaluation

How to validate must null if another field has specific value or not null
In my case it is the opposite of required_if with multiple values
$rule = array(
'selection' => 'required',
'stext' => 'required_if:selection,2|required_if:selection,3',// stext should be null if selection is 2 or 3
);
And if needed how to perform own validation?
So in your example you can do something like this:
$rule = array(
'selection' => 'required',
'stext' => 'required'
);
// override the rule
if(in_array(request('selection'), [2, 3]))
{
$rule['stext'] = 'nullable';
}
This means if the selection is 2 the field will be required and if the selection field has any other value the stext field will be required.
I am not sure if I understood your question correctly. In any case the opposite of required_if is required_without so you can use that one if you want this field to be required even if the selection is empty.
With custom rule your passes method should look like this:
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class CustomRule implements Rule
{
protected $selection;
public __construct($selection)
{
$this->selection = $selection;
}
public function passes($attribute, $value)
{
return $value === null && in_array($this->selection, [2, 3]);
}
}
You use it like this:
$rule['stext'] = [ new CustomRule(request('selection') ]
I try to extend the validation rule. put the following in AppServiceProvider:
Validator::extend('null_if', function ($attribute, $value, $parameters, $validator) {
$other = $parameters[0];
$other_value = array_get(request()->toArray(), $other);
if ($parameters[1] == $other_value) {
return empty($value);
}
return true;
});
Tell me if it's work or what error given to you.

Laravel custom validation rule. How to add possibility for passing rule with a string representation instead of using class name?

What do I mean:
As it's shown at documentation:
...
'field' => [
'required',
'numeric',
new MyCustomRule
],
...
But what if I want to pass it in one string and with some arguments||options signature (as it's implemented with default "exists" rule where i can optionally pass connection, table, field, column and so on)?
...
'field' => 'required|numeric|my_rule:param1.param2,option1,option2',
...
Where should i define signature? Thanks!
Extend your validator inside App\Providers\AppServiceProvider
E.g:
Validator::extend('rule', function (string $attribute, string $value, array $parameters) {
dump($attribute, $value, $parameters);
return $attribute == $value;
});
See a working example here.

Laravel: rules request to look up in database-attribute has to be set as Y

After sending the data of a formula the input values will be checked first by the defined rules.
After this a input value will be checked if it is in the database and if its attribute is set as 'Y'.
How can I define that in the formula rules request?
Thank you in advance!
For this behaviour you should implement a custom validator.
For example the code may look like:
\Validator::extend('validator1', function ($attribute, $value, $parameters) {
//do some logic here
// return true or false
});
\Validator::extend('validator2', function ($attribute, $value, $parameters) {
return \DB::table('table')->where('field1', $value)->where('field2', 'Y')->exists();
});
$validationRules = [
'field' => 'validator1|validator2'
];
Read more here https://laravel.com/docs/5.3/validation#custom-validation-rules

yii2 custom validation not working

I need to compare 2 attribute value in the model and only if first value is lower than second value form can validate.I try with below code but it not worked.
controller
public function actionOpanningBalance(){
$model = new Bill();
if ($model->load(Yii::$app->request->post())) {
$model->created_at = \Yii::$app->user->identity->id;
$model->save();
}else{
return $this->render('OpanningBalance', [
'model' => $model,
]);
}
}
Model
public function rules()
{
return [
[['outlet_id', 'sr_id', 'bill_number', 'bill_date', 'created_at', 'created_date','bill_amount','credit_amount'], 'required'],
[['outlet_id', 'sr_id', 'created_at', 'updated_at'], 'integer'],
[['bill_date', 'd_slip_date', 'cheque_date', 'created_date', 'updated_date','status'], 'safe'],
[['bill_amount', 'cash_amount', 'cheque_amount', 'credit_amount'], 'number'],
[['comment'], 'string'],
['credit_amount',function compareValue($attribute,$param){
if($this->$attribute > $this->bill_amount){
$this->addError($attribute, 'Credit amount should less than Bill amount');
}],
[['bill_number', 'd_slip_no', 'bank', 'branch'], 'string', 'max' => 225],
[['cheque_number'], 'string', 'max' => 100],
[['bill_number'], 'unique']
];
}
}
It's going in to the validator function but not add the error like i wanted
$this->addError($attribute, 'Credit amount should less than Bill amount');
anyone can help me with this?
If the validation is not adding any error, it's most likely being skipped. The issue is most likely becasue of default rules behaviour whereby it skips empty or already error given values as per here: https://www.yiiframework.com/doc/guide/2.0/en/input-validation#inline-validators
Specifically:
By default, inline validators will not be applied if their associated attributes receive empty inputs or if they have already failed some validation rules. If you want to make sure a rule is always applied, you may configure the skipOnEmpty and/or skipOnError properties to be false in the rule declarations.
So you would need to set up the skipOnEmpty or skipOnError values depending on what works for you:
[
['country', 'validateCountry', 'skipOnEmpty' => false, 'skipOnError' => false],
]
Try this:
public function actionOpanningBalance(){
$model = new Bill();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->created_at = \Yii::$app->user->identity->id;
$model->save();
}else{
return $this->render('OpanningBalance', [
'model' => $model,
]);
}
}
For Validation
You can use anonymous function :
['credit_amount',function ($attribute, $params) {
if ($this->$attribute > $this->bill_amount)) {
$this->addError($attribute, 'Credit amount should less than Bill amount.');
return false;
}
}],
you can use like this below answer is also write
public function rules(){
return [
['credit_amount','custom_function_validation', 'on' =>'scenario'];
}
public function custom_function_validation($attribute){
// add custom validation
if ($this->$attribute < $this->cash_amount)
$this->addError($attribute,'Credit amount should less than Bill amount.');
}
I've made custom_function_validation working using 3rd params like this:
public function is18yo($attribute, $params, $validator)
{
$dobDate = new DateTime($this->$attribute);
$now = new DateTime();
if ($now->diff($dobDate)->y < 18) {
$validator->addError($this, $attribute, 'At least 18 years old');
return false;
}
}
This is a back end validation and it will trigger on submit only. So you can try something like this inside your validation function.
if (!$this->hasErrors()) {
// Your validation code goes here.
}
If you check the basic Yii2 app generated you can see that example in file models/LoginForm.php, there is a function named validatePassword.
Validation will trigger only after submitting the form.

Resources