How to Set Form Validation Rules for CodeIgniter Dynamically? - php

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().

Related

TYPO3 fluid select property remains empty after submit

Im creating an edit page for my model where I have the following code:
<f:form action="createEditSave" addQueryString="1" method="POST" object="{activity}" objectName="activity">
<f:form.select property="competence" options="{competences}" prependOptionLabel="" prependOptionValue="" optionLabelField="name" />
</f:form>
When I submit the form(and select an option in the select) I expect the model in my createEditSaveAction to contain in this case a competence. But it remains empty even though the request does contain the argument. Am I wrong in thinking it should automatically select the object and must I handle it myself in my createEditSaveAction?
I believe my html is correct.
When submitting my form I receive no validation errors and get correctly send to my createEditSaveAction. Only here I expect my Activity model to have a competence model but the setCompetence() function receives a empty objectStorage.
Depends on what happened to send you back to the form:
If the problem was validation errors the value should be prefilled since it will exist in the request data from the referring request, which is then read by the ViewHelper to determine the current value.
If you redirected to an edit action the property value only exists on the object you passed and if that object is, for example, not assigned as a template variable in the action that displays your form.
It may help if you specify the optionValueField property - and it may also help if you explicitly pass a value for the field.
Don't forget that if your use case is somehow too specialised to fit this, you can always use f:form.select.option in a loop to render options manually, including selected attribute.
Final word: from the naming of your action it looks like you have one action that is capable of both creating and updating an object. This is bad practice - you should be using two different actions for this, and on the "new" action your object argument should be optional and null by default, on "edit" it should be mandatory. It may also be a good opportunity to review your controller in general, to confirm that it actually does use properly declared and annotated arguments and argument types for all the actions. If you circumvent the framework, things like form validation and subsequently resolving of field values may not work like you expect.
Resolved my own issue. The problem was the annotation in my model which said it was a objectStorage.
Had a similar issue with my form, I had to include both the name and the propery tag.
<f:form.select name="foo" property="foo">
<f:form.select.option value="bar">Bar</f:form.select.option>
</f:form.select>

Testing for POST in Yii 2.0

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!

How to enable query builder for is_unique form validation in CodeIgniter?

I have a question about enabling the is_unique() rule for form validation in CodeIgniter.
In another explanation (link), they don't include the model query builder for standard usage of is_unique()
I need to use the rule is_unique(table.field) for my id field.
What should I do for making this function work on my model file to initiate table.field from my database? Because at documentation, I didn't see an explanation for enabling the is_unique rule.
My current code is still use matching data manually, but I need to know how to use this rules
$this->form_validation->set_rules('siteid', 'Site ID', 'trim|required|max_length[100]|is_unique[site_tower.site_id_tlp]');
I have just gone through the link you posted, There are 2 ways to use such validation. If you have set in your configuration files.
With that you can use the code as is is_unique[TABLE_NAME.FIELD] and it will work automatically. But at times this logic might not necessarily meet your need and you will need something more complex.
For example lets say you have a members registration that requires you to check if the email already exists, you can run is_unique and it will work perfectly. Now let's say you want to edit the same member, running is_unique on an edit function will render the user unable to save the data if no data is edited. WHY? because is_unique would determine that the email is already registered although it belongs to the current user that is being edited.
How do we fix this? We run our own callback in which we specify the logic.
You do it by specifying a method within the controller (or a model -- slightly different) but you prefix the method name with callback_ so that it is detected.
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
This will then look for a method in your controller called 'username_check'
public function username_check($str)
{
if ($str == 'test')
{
$this->form_validation->set_message('username_check', 'The {field} field can not be the word "test"');
return FALSE;
}
else
{
return TRUE;
}
}
Of course you can use a query within the callback to check against the db rather than check for just a string as it shows in the example.
more information can be found on Ci3 documentation.
LINK
Use CTRL + F and search for callback or is_unique
You might have missed this?
$this->load->library('database');
works instantly after adding database lib.

Yii - remove url rule dynamically

Is there any possible way to remove a url rule from the urlManager on the go?
I know I can add a rule via urlManager->addRules(), but how do I delete them?
Thanks.
EDIT:
My aim is to generate the rules dynamically based on the subdomain.
For example, a subdomain of certain type would have a rule <catalog>/<brand>/<product> leading to a certain product, while the other would have a different rule. Also, the subdomains are also dynamic, meaning that I can't create any static conditions.
You have all rules here:
Yii::app()->urlManager->rules;
That's an associative array, you can easily loop through it and manipulate it.
It would be great, if you could provide more details about why you need such behavior.
In common, you can extend default CUrlManager class and add needed functions. After that you can specify this new, let's say, CustomUrlManager in config.php as implementation for your urlManager.
But again - what problem do you try to solve?
Unfortunately, there wasn't a clear way to solve this problem.
The inner rules array _rules is declared private, and there are no methods for working with it apart from addRules(). This method, however, only allows you to append the processed rules to the start/end of the _rules array. You won't be able to delete the rules you've added, too.
The solution I came up with is bad practice, but there was no other way of working around my issue (that I know of).
Declare a method inside CUrlManager
protected function clearInnerRules() {
$this->_rules = array(); // clears the inner rules array
}
In the child class UrlManager that is used as the manager for the Yii app, declare:
public function reprocessRules() {
Yii::app()->cache->delete(self::CACHE_KEY); // remove anything rule-connected from cache
$this->clearInnerRules();
$this->processRules();
}
Using the onBeginRequest event, add rules to the placeholders in the array:
// code
Yii::app()->urlManager->rules['rulePlaceholder'] = $newRule;
Yii::app()->urlManager->reprocessRules();
// code
Done. Now I can easily delete the rules or replace them at any moment (provided, this moment is before the request). Sometimes you just gotta do what you gotta do, I guess.

CakePHP 1.3 - Validate input is numeric within view/controller?

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');
}
}

Categories