Does Laravel validation provide any ways to fail when request contains input keys that are not defined in validation rules? Ex: Validator is instantiated with the following rules: ['name' => 'required', 'email' => 'required|email']. I want validation to fail if $request contains any other keys except name and email (Think of a user POSTing to the route end-point with undesirable data). Is that possible to achieve with simple validation rules?
P.S. I am aware of mass-assignment tricks with Eloquent, however I need to perform strict validation before any data is manipulated / persisted.
No, it's not possible to achieve with simple validation rules but would be easy to add.
All you would need to do is something like the following...
if ( count(request()->except(['name', 'email']) ) > 0) {
return false;
}
Related
Given this on the model:
public $validate = [
'amount' => array(
'rule' => array('comparison', '>=', 0),
'message' => 'You must buy over 0 of this item!'
)
];
How can I validate param #2 of the below?
public function buy(int $item, int $amount) {
Validation seems to be built only for POST, which I'd like to opt out of here.
First things first, modifying the database with GET requests is an anti-pattern for many different reasons. Even if you assume a friendly user agent (which you never should!), browsers can behave quirky and do unexpected stuff like for example sending GET request multiple times (that is perfectly valid as GET is not ment to modify data), which they usually won't for POST/PUT/DELETE.
I would strongly suggest to change your endpoint to handle POST requests instead.
That being said, you can generally validate whatever you want, the validation mechanisms first and foremost just validate data, they don't know or care where it stems from. You can hand over whatever data you want to your model, and let it validate it:
$data = array(
'item' => $item,
'amount' => $amount,
);
$this->ModelName->set($data);
if ($this->ModelName->validates()) {
// data is valid
} else {
// data is invalid
$errors = $this->ModelName->validationErrors;
}
Moreover you can use CakePHP's validation methods completely manually too:
App::uses('Utility', 'Validation');
$isValid = Validation::comparison($amount, '>' 0);
This example of course doesn't make too much sense, given that $isValid = $amount > 0 would do the same, however it should just show that you can validate anything everywhere without models being involved.
See also
Cookbook > Models > Data Validation > Validating Data from the Controller
Cookbook > Models > Data Validation > Core Validation Rules
I do have a registration form in my laravel 5.4 application and laravel form request validation is used for server side validation. Some fields in this form are populated dynamically using calculations in javascript which need to be validated against user inputs.
The user input fields in the form are 'quantity', 'rate' and 'discount'.
The populated fields are 'total' and 'bill_amount'.
What i need to validate are :
Check 'total' equal to 'quantity' * 'rate'.
Check 'bill_amount' equal to 'total' - 'rate'
I would prefer laravel form request validation methods for this validation. I have tried to use methods like After Hooks and conditionally adding rule etc. and failed.
In simple words the requirement is : check if a field is equal to product of other two fields, and invalidate if not equal and validate if equal.(using form request validation.)
Thanks in advance!
After a long time I was able to find this solution.
Form request After Hooks can be used to achieve the result:
[I was unable to find this logic before]
public function withValidator($validator)
{
$quanty = $this->request->get("quantity");
$rate = $this->request->get("rate");
$billAmount = $this->request->get("bill_amount");
$validator->after(function ($validator) {
if(($quanty * $rate) != $billAmount) {
$validator->errors()->add('bill_amount', 'Something went wrong with this field!');
}
});
}
I have some doubt about safe validator.There is four case
i)I have some validation rule like below
[['name'], 'required','message' => 'You must enter name'],
In that case i want safe validation or it is enough
ii)I have some validation rule with some scenarios like below
public function scenarios()
{
return [
self::SCENARIO_INFO => ['title', 'phone'],
];
}
rule like that
[['title'], 'required','message' => 'You must enter Title','on' => 'info'],
In that case also i want safe validation or it is enough.
iii)Third case i have only public property no validation rules apply in that property,but i want that property in form user will enter.
iv)Fourth case i have only public property no validation rules apply in that property,and i don't want that property even form also,using only internally (i.e model).
In which cases the safe validation rule is must,i am new in yii so please explain easily understandable way.Thanks in advance
From the cases you have provided, it appears case# iii) will be the right situation for using safe.
For proper understanding please get your concepts clear about Safe Attributes, Massive Assignments. Refer to the links below:
http://www.yiiframework.com/doc-2.0/guide-structure-models.html#massive-assignment
http://www.yiiframework.com/doc-2.0/guide-structure-models.html#safe-attributes
i'll try and be as clear as possible.
I'm working on some form validation using the wonderful kohana framework. However i have come at a crossroads and not sure whether the way i have taken is a wise choice.
Basically, i have a date selector using several select boxes (i toyed with the idea of using javascript date pickers but the select boxes proved to be more suitable for my purpose) and a date field in a database. I wanted to concatenate these select boxes into the date field so it can be checked to make sure its valid.
protected $_rules = array(
'mydate' => array(
'not_empty' => NULL,
'date' => NULL,
),
);
Now to me, it makes most sense to include the validation in the model, since that's where the data layer is in the MVC pattern, so i decided to create some class attributes named $_rules, $_filters and $_callbacks, each set as protected and with my basic rules applied. And then a function in the model that sets up a validation object using these attributes and returning it to whatever controller is calling it, then the controller can just run the validation and the job is done.
My problem comes when i want to concat these select boxes, to me it makes most sense to make a custom filter and pass in the post data, but with the filters rules and callbacks being attributes, i can't add any variables to them. My current solution is to manually add the extra filter in when the validation setup function is being run something similar to this:
public function setupValid($post) {
$this->_filters['mydatefield'] = array(
'MyClass::MyConcat' => array($post);
);
//creates a validation object and adds all the filters rules and callbacks
}
But i don't feel this is the cleanest solution, i'm probably nit picking as the solution works the way i require it to. However i'm not sure whether a filter was ever intended to do such a thing as this, or whether this should be a callback as the callback has access to the array by default, but then again callbacks are called last, which would mean i couldn't apply any rules like, 'not_empty' (not important in this case since they are pre populated select boxes, but might be in another case)
So i guess my question is, am i using filters as they were intended to be used?
I hope i've managed to explain this clearly.
Thanks
you need to keep in mind that you should only validate fields inside the $_rules that are very important to your database or business logic.
so for example if you would try to setup other form somewhere else in your app or you would provide a restfull api for your app, validation of the field 'day_field_(that_doesnt_exists_in_the_database_and_is_used_to_privide_a_better_ux_in_this_one_form)' => array('not_empty' => NULL) will give you a hard time to do that.
so i suggest you to keep your $_rules like they are now and provide some logic to your values() method:
// MODEL:
public function values($values)
{
if ( ! empty($values['day']) && ! empty($values['month']) && ! empty($values['year']))
{
$values['mydate'] = $values['year'].'-'.$values['month'].'-'.$values['day'];
}
return parent::values($values);
}
// CONTROLLER:
if ($orm->values($form['form_array'])->check())
{
$orm->save();
}
else
{
$this->template->errors = $orm->validate()->errors('validation');
}
I want to ovveride the default url() validation method in CakePHP, since it does not allow the use of ~ inside urls. I thought it would be enough to declare a url() method in AppModel, but it seems that core methods have the precedence with respect to user defined ones.
I think (but I have not tried) one possible way would be to use
$validate = array('url' => array(
'rule' => array('Userdefined', 'url'),
'message' => 'This is not an URL!!!'
));
or something like that (what is the correct sintax?). But this is not completely satisfying.
Indeed I pass the $validate variable as a JSON object to my javascript, and then I do client validation accordingly. Basically I have rewritten part of the CakePHP validation automagic in javascript. So I really want to have
$validate = array('url' => array(
'rule' => 'url',
'message' => 'This is not an URL!!!'
));
in order not to break client-side validation.
EDIT: It turns out I were wrong. The problem is that methods in Validation are called differently from methods in Model, so one has to pay attention when copying/pasting.
The first difference is that $check will now be an array instead of a string, but this I already figured out. What I did not realize is that another array of parameters is passed to Validation methods in Model. Since the signature of url() was
url($check, $strict = false)
the result was that $strict always had the value true, thereby requiring full URLs with protocol prefix. Seeing that the intended URL with tilde was not validating I assumed that the problem was that CakePHP still used the old method.
Why not just use the custom validation and make an url validation function with a different name?
Otherwise the manual says that you can override the Validation classes methods with functions in either the AppModel, Model, or Behaviors.
Here is the relevant link in the book.
http://book.cakephp.org/view/150/Custom-Validation-Rules#Adding-your-own-Validation-Methods-152