I need to validate that a form input is numeric in CakePHP 1.3. However, the input is not a property of the model, so I don't think I should try to set the validation for it in the model. Instead, some calculations are done on that input and the results are used in the resulting model object. How can I validate this in the view/controller? That is, check that what the user input was numeric and show a validation error message if not before passing it through the calculations? Thanks!
There's nothing wrong with defining model validation rules for non-existing / calculated fields, but you can also use the Validation class which might be cleaner. See 1 and 2.
If you use jquery at least you don't have to do a full page reload to check. Especially if it's only for one value. Just another option, see if it helps!
if($('#Field').val() != "")
{
if(!($.isNumeric($('#Field').val())) {
alert('value must be numeric');
}
}
Related
I have a template that allows adding new lines. Example: I want to add multiple products at once to a store, so I can add them all at once, through those lines that replicate themselves. The problem is that I need to validate these fields, they are all mandatory. I'm implementing so that I can walk through each one and leave it compulsory. However, I came across another problem, Laravel is telling me that my field is empty, but it is not. I would like to know how I can solve it, thank you in advance.
Here is my code to FormRequest
public function rules()
{
$rules = [];
foreach($_POST['esp'] as $key => $esp){
$name_field = "esp[" . $key . "]" . "[esprqe]"; //name of my field is complicated even as it is time based
$rules[$name_field] = 'required';
}
return $rules;
}
My template is big, no need to show.
message I receive: esp[1553533952015][esprqe]: ["The esp[1553533952015][esprqe] field is required."]
My input is not empty, I do not know what the problem is
You state the name of your field 'esprqe' is time based and complicated. This is likely the cause of your problem.
The esp['.$key.'] field is probably fine, as this field is transferred from your form. However, the value that goes into esprqe, if that is being generated in your server side code above (I don't know, you haven't provided how this field is generated), and if the rules are looking for that field to match a time-based generated field on the form... those values won't match and you will have a non-value coming into your method above.
This would very likely generate a message
["The esp[1553533952015][esprqe] field is required."]
If this is your issue, you can test by first creating a simple numbered index for the esprqe field that will be matched on both form and method. If this succeeds, you can then increase the complexity using a common generator so that the rules section knows exactly what the name of the field is. Time can't be common between form creation and rules creation - thus perhaps the reason for the failure.
You need use "dot notation" to validate attributes within an array.
$name_field = "esp.$key.esprqe";
Laravel Docs: validating arrays
I have a validation rule in one of my Table classes like this:
public function validationDefault(Validator $validator)
{
$validator
->scalar('comment')
->maxLength('comment', 3000)
->requirePresence('comment', 'create')
->notEmpty('comment');
return $validator;
}
This validates the comment field of an input and means it cannot be over 3000 characters in length. All of this is fine when working in PHP.
One part of my application uses a JavaScript character counter - it tells the user how many remaining characters they have in a field as they type. The js for this works fine, with the limit 3000 hardcoded.
However, I want to know if there's a way to avoid hardcoding this limit in my js? Because otherwise my code is not DRY as I'm defining the 3000 limit in multiple places and if it changes that's problematic to remember/update.
Is it possible to read the maxLength property directly from validationDefault for the comment field? This question concerns how to access the data defined in the Table class; I am fine with knowing how to pass it to js via ajax.
I haven't got any further code to show as I don't know if/how this is even possible.
CakePHP 3.5.13
To get validation rule value, you have to get Validator from Table, then get ValidationSet, and then ValidationRule, from which you can extract desired result. Sample controller code below:
$validator = $this->YourTable->getValidator("default");
$validationSet = $validator->field("comment");
$validationRule = $validationSet->rule("maxLength");
$result = $validationRule->get("pass");
Or, in just one line:
$result = $this->YourTable->getValidator("default")->field("comment")->rule("maxLength")->get("pass");
A returned value will be an array of additional arguments passed to validation rule, in your case it should look like:
array(1) {
[0]=>
int(3000)
}
Also, #ndm in his answer mentioned about other posibilities:
On form helper/context level it's also possible to read the schema, and support for transalting its length configuration and the validation rule value into a maxlength HTML attribute is being implemented for CakePHP 3.7
Further reading:
Getting validators from tables
Validator class
ValidationSet class
ValidationRule class
In my controllers that Gii creates it is common to see the following:
if($model->load(Yii::$app->request->post()) && $model->save()){
//.....do something such as redirect after save....//
}else
{
//.....render the form in initial state.....//
}
This works to test whether a POST is sent from my form && the model that I am specifying has saved the posted information (as I understand it).
I've done this similarly in controllers that I have created myself but in some situations this conditional gets bypassed because one or both of these conditions is failing and the form simply gets rendered in the initial state after I have submitted the form and I can see the POST going over the network.
Can someone explain why this conditional would fail? I believe the problem is with the 'Yii::$app->request->post()' because I have removed the '$model->save()' piece to test and it still bypasses the conditional.
Example code where it fails in my controller:
public function actionFreqopts()
{
$join = new FreqSubtypeJoin();
$options = new Frequency();
$model = new CreateCrystal();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$model->insertFreqopts();
return $this->redirect(['fieldmap', 'id' => $join->id]);
} else {
return $this->render('freqopts', ['join' => $join, 'options' => $options]);
}
}
My initial thought was that I'm not specifying the correct "$model" in that I'm trying to save the posted data to FreqSubtypeJoin() in this case and the $model is CreateCrystal(); however, even when I change the model in this conditional it still fails. It would be helpful if someone could briefly explain what the method 'load' is actually doing in layman's terms if possible.
The load() method of Model class is basically populating the model with data from the user, e.g. a post query.
To do this it firstly loads your array of data in a form that matches how Yii stores your record. It assumes that the data you are trying to load is in the form
_POST['Model name']['attribute name']
This is the first thing to check, and, as long as your _POST data is actually getting to the controller, is often where load() fails, especially if you've set your own field names in the form. This is why if you change the model, the model will not load.
It then check to see what attributes can be massively assigned. This just means whether the attributes can be assigned en-mass, like in the $model->load() way, or whether they have to be set one at a time, like in
$model->title = "Some title";
To decide whether or not an attribute can be massively assigned, Yii looks at your validation rules and your scenarios. It doesn't validate them yet, but if there is a validation rule present for that attribute, in that scenario, then it assumes it can be massively assigned.
So, the next things to check is scenarios. If you've not set any, or haven't used them, then there should be no problem here. Yii will use the default scenario which contains all the attributes that you have validation rules for. If you have used scenarios, then Yii will only allow you to load the attributes that you have declared in your scenario.
The next thing to check is your validation rules. Yii will only allow you to massively assign attributes that have associated rules.
These last two will not usually cause load() to fail, you will just get an incomplete model, so if your model is not loading then I'd suggest looking at the way the data is being submitted from the form and check the array of _POST data being sent. Make sure it has the form I suggested above.
I hope this helps!
There is a sample in the bottom of the official documentation http://kohanaframework.org/3.2/guide/kohana/security/validation
But obviously it wont work at the request as long as $post['username'] in View is used but the $post array is empty on first request.
So how do you restore the values in this case? Any general solution?
PS: yes, I do understand I could do isset($post['username']) ? $post['username'] : ''; but it is just annoying
I use the model to display the data in the form. That way the initial form value is the initial value in the model.
I then update the model data with POST data in the controller, if there are validation errors, the model data will contain the POST data. This means I don't have to put any conditional logic in the view, and I just do: Form::input('name', $model->name)
Here's a more detailed explanation of this approach: Kohana ORM and Validation, having problems
I use Arr::get function:
echo Form::input('name', Arr::get($post, 'name'))
I was just looking at the old documentation on Building and Validating a Form.
You can see from the sample code that first you need to initialize an array with the form field names as the key and set the value to an empty string. And if there's an error, fill in the values of each element. In the views, you can simply call Form::input() normally without any if statement or some sort.
I guess Kohana has already been built this way from the start. And it doesn't seem to change. You'll probably just need to do the same thing.
With the new version of CodeIgniter; you can only set rules in a static form_validation.php file. I need to analyze the posted info (i.e. only if they select a checkbox). Only then do I want certain fields to be validated. What's the best way to do this, or must I use the old form validation class that is deprecated now?
You cannot only set rules in the config/form_validation.php file. You can also set them with:
$this->form_validation->set_rules();
More info on: http://codeigniter.com/user_guide/libraries/form_validation.html#validationrules
However, the order of preference that CI has, is to first check if there are rules set with set_rules(), if not, see if there are rules defined in the config file.
So, if you have added rules in the config file, but you make a call to set_rules() in the action, the config rules will never be reached.
Knowing that, for conditional validations, I would have a specific method in a model that initializes the form_validation object depending on the input (for that particular action). The typical situation where I've had the need to do this, is on validating shipping and billing addresses (are they the same or different).
Hope that helps. :)
You could write your own function which checks whether said checkbox is selected, and applies the validation manually.
function checkbox_selected($content) {
if (isset($_REQUEST['checkbox'])) {
return valid_email($content);
}
}
$this->form_validation->set_rules('email', 'Email', 'callback_checkbox_selected');
If you want to avoid writing your own validation function, I came across this site which suggests that, if you're dynamically setting your rules using the Form Validation class, you can simply build up the rule string argument to set_rules() dynamically.
You first test the POST data to determine if your condition is satisfied (eg. checkbox selected) and then, as necessary, add a "|required" to the rule string you pass to set_rules().