I've had the most frustrating time trying to play with CakePHP 2's validation mechanisms. I am trying to allow for an input to be empty, yet still run a custom validation rule. However, if I use "allowEmpty" => true, it bypasses my custom validation rule.
Code
// in $validate array
...
'company_role' => array(
'reqIfFieldValueEquals' => array(
'rule' => array('reqIfFieldValueEquals', 'individual_or_company', 'company'),
'message' => 'You must provide your role with the company!',
'allowEmpty' => true,
'required' => true
),
),
...
// my custom validation rule which will NOT run! >:(
public function reqIfFieldValueEquals($field, $compare_field, $value) {
$fieldValue = false;
foreach ($field as $name => $val) {
$fieldValue = $val;
}
$valueToCheck = $this->data[$this->name][$compare_field];
if ($valueToCheck === $value) {
return !empty($fieldValue);
}
return true;
}
Q How in the world can I allow for an empty input, yet still run my custom validation rule?
Not sure why you need validation on empty input, but can you try to disable allow input, and simply return true in the validation rule if the input is empty?
Related
I am trying to set a field as reuired only when another field selected value not equal to 11.
I have tried this example
array('role', 'ext.YiiConditionalValidator',
'if' => array(
array('role', 'compare', 'compareValue'=>"11"),
),
'then' => array(
array('company_id', 'required'),
),
),
),
I tried downloading new ConditionalValidator.
And even tried custom condition:
public function checkEndDate($attributes,$params)
{
$this->addError('company_id','Error Message');
}
public function rules() {
return array(
array('company_id', 'checkEndDate')
);
}
But it all shows error. Any simple way to solve this?.
Why not using scenarios? If you're creating/editing model with 'customer_type=active' you can before hand create it with special scenario:
$model = new MyModel(MyModel::SCENARIO_ACTIVE);
and then define your rules including scenario:
array('birthdate, city', 'required', 'on' => MyModel::SCENARIO_ACTIVE),
array('city', 'in', 'range' => array("sao_paulo", "sumare", "jacarezinho"), 'on' => MyModel::SCENARIO_ACTIVE)
If you don't like this way, you can always very simply create your own validator.
In rules:
array('customer_type', 'myCustomValidator'),
In the model class:
function myCustomValidator(){
if($this->customer_type == 'active'){
...
if($error){
$this->addError(...);
}
}
}
I have searched far and wide, tried every trick in the book, but I still can't get my CakePHP application to perform simple Password Confirm validation. I've tried creating a custom validation rule like this:
'passwordequal' => array('rule' => 'checkpasswords' , 'message' => 'Passwords Do Not Match')
Then defined 'checkpasswords' like this:
public function checkpasswords(){
if(strcmp($this->data['User']['new_password'],$this->data['User']['confirm_password']) == 0 )
{
return true;
}
return false;
}
'new_password' and 'confirm_password' are the password input fields. This didn't work. Then I tried one in which I hashed the 'confirm_password'. That didn't work either. I have other 'rules' as well that are not being validated, like 'notempty', which I believe is one of the standard CakePHP rules. Can anybody please help. I know this question has been asked a few times but none of those solutions have worked for me. CakePHP documentation hasn't helped much either.
two fields in view file
echo $this->Form->input('password');
echo $this->Form->input('repass');
Model file
<?php
class Post extends AppModel {
public $validate = array(
'repass' => array(
'equaltofield' => array(
'rule' => array('equaltofield','password'),
'message' => 'Require the same value to password.',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
'on' => 'create', // Limit validation to 'create' or 'update' operations
)
)
);
function equaltofield($check,$otherfield)
{
//get name of field
$fname = '';
foreach ($check as $key => $value){
$fname = $key;
break;
}
return $this->data[$this->name][$otherfield] === $this->data[$this->name][$fname];
}
}?>
Seems like your model is not loading correctly and using a dynamically generated model.
Comparing passwords in 2.x is nothing more than comparing any two fields as cake no longer hashes the pw automatically.
Can you confirm your validation method is being run, seems like its not especially if simple things like notEmpty is not working.
User Model
//...
public $validate = array(
"username" => array(
"alpha-numeric" => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Username must contain only numbers and letters.'
),
"between" => array(
"rule" => array("between", 4, 25),
"message" => "Username must contain between 4 to 25 characters."
)
),
//...
User Controller
public function index() {
debug($this->data); // displays values as expected
debug($this->User->validates()); // always false, unless I remove alphanumeric rule
}
On submit, my form will always validate the username field as false (triggering its corresponding message), no matter what is in the text. The remaining fields are also not validated. If I remove the username validation rules all together, the remaining fields are still not validated. (Form is submitted as though validated)
What am I missing here?
Before manually calling $this->User->validates(), you must call the model's set method and provide the form's data.
public function index() {
$this->User->set($this->request->data); // Only way the next method will work.
debug($this->User->validates());
}
I wanted to incorporate GUMP https://github.com/Wixel/GUMP into my site for server side validation. But unfortunately the documentation is light and I am new to PHP.
Here is my validation code:
//Validation
$gump = new GUMP();
$rules = array(
'dept' => 'required|numeric',
'hosp' => 'required|numeric',
'subhosp' => 'required|numeric',
'user' => 'required|numeric',
'gpo' => 'required|boolean|exact_len,1',
'clin' => 'required|valid_name',
'clinmail' => 'required|valid_email',
'comp' => 'required|alpha_dash',
'cpt' => 'required|alpha_dash',
'past' => 'required|boolean|exact_len,1',
'latex' => 'required|boolean|exact_len,1',
);
$validated = $gump->validate($_POST,$rules);
print_r($validated); // Something went wrong
The output from the above code gives me an array like so when I am looking at my AJAX response in FireBug:
Array
(
[0] => Array
(
[field] => clin
[value] => .-0
[rule] => validate_valid_name
)
[1] => Array
(
[field] => clinmail
[value] => %$sd
[rule] => validate_valid_email
)
)
And I what I need is something like so:
<div class="error-msg">You did not enter a valid email address</div><br>
<div class="error-msg">You did not enter a valid username</div><br>
From the documentation I get:
if($validated === TRUE)
{
// Do something, everything went well
}
else
{
// This is where I am stuck. Do I have to loop through and put my <div> tags here?
}
My question is how would the community handle outputting error messages with this class? My only thought is that I loop through the results above and output different messages depending on the field and the rule that was broken but that seems tedious. Is there a better way or a better class to use that does standalone PHP input validation? I was using another very easy to use class but it started breaking when I moved away from inline PHP to AJAX.
edit your code to:
$gump = new GUMP();
$rules = array(
'dept' => 'required|numeric',
'hosp' => 'required|numeric',
'subhosp' => 'required|numeric',
'user' => 'required|numeric',
'gpo' => 'required|boolean|exact_len,1',
'clin' => 'required|valid_name',
'clinmail' => 'required|valid_email',
'comp' => 'required|alpha_dash',
'cpt' => 'required|alpha_dash',
'past' => 'required|boolean|exact_len,1',
'latex' => 'required|boolean|exact_len,1',
);
$error_texts = array(
'dept' => 'You must enter a numeric value',
'hosp' => 'You must enter a numeric value',
'subhosp' => 'You must enter a numeric value',
'user' => 'You must enter a numeric value',
'gpo' => 'You must enter a boolean value',
'clin' => 'You must enter a valid name',
'clinmail' => 'You must enter a valid email',
'comp' => 'You must enter a valid alpha dash',
'cpt' => 'You must enter a valid alpha dash',
'past' => 'You must enter 1 char',
'latex' => 'You must enter 1 char',
);
$validated = $gump->validate($_POST,$rules);
if($validated === TRUE)
{
echo "Every thing is ok";
}
else
{
foreach($validated as $key=>$error)
{
echo '<div class="error-msg">' . $error_texts["{$error['field']}"] . '</div><br />';
}
}
I would like to add that if a validation fails twice, for example if a value is required and has to exist out of more than 10 characters then #semsems answer would print multiple lines for the same field.
I changed the above code and added:
$_validated = array();
foreach($validated as $key=>$error)
{
if ( !in_array($error['field'], $_validated) )
{
print '<div class="error-msg">' . $error_texts["{$error['field']}"] . '</div>';
$_validated[] = $error['field'];
}
}
I know this question is a year old and been answered, but since I based myself on the accepted answer and in my view made it a sweet better (completely generic with locale as extra), I thought it would be nice to share and get some feedback... what do you guys think about my code? Now based on semsem's answer... I like the way he coded part of it and I derived from it to come up with the following code:
First I extended GUMP with my own class so I could overwrite some functions
<?php
require("gump.class.php");
class GumpValidator extends GUMP
{
private $locale;
private $translator;
public function GumpValidator($lang = "en")
{
$this->locale = $lang;
$this->loadValidationLocales();
}
/** Overwrite the default validate() function of GUMP so that I can add an extra "message" property */
public function validate(array $input, array $ruleset)
{
$validated_data = GUMP::validate($input, $ruleset);
if(is_array($validated_data)) {
foreach($validated_data as $index=>$error) {
$validation = str_replace(":attribute", $error['field'], $this->translator[$error['rule']]);
$validation = str_replace(":param", $error['param'], $validation);
$validated_data[$index++]['message'] = $validation;
}
}
return $validated_data;
}
/** Depending on the language locale, load the proper set of validation messages */
private function loadValidationLocales()
{
$this->translator = require "/lang/" . $this->locale . "/validation.php";
return $this->translator;
}
} // EOC
Then as you can see from the extended class, I created myself a set of locale language message for validation and I took the full list of possible validation errors directly from the GUMP code on Github, take a look at the function get_readable_errors() to get the full list of errors. Github link here... The locales which I created are saved under separate language folders /lang/en/validation.php, /lang/fr/validation.php, etc... You can easily create as many as you want... I took the concept from Laravel Framework... These validation.php files looks for example, like this (1 file per language/locale), here is the English one:
<?php
return array(
"validate_alpha" => "The :attribute may only contain letters.",
"validate_alpha_numeric" => "The :attribute may only contain letters and numbers.",
.....
);
Then finally in my POST to validate code I just call it like this:
// load my extended class with language locale I want to use
$gump = new GumpValidator("en");
// now validate the data
$validated_data = $gump->validate( $_POST, $rules );
So at the end I get the extra property of message inside the $validated_data object returned with the option of whichever locale language I chose to display the error message...and voilĂ !!! In my case I read the code in javascript to display the errors in Bootstrap alert, but if you want PHP you can look at semsem answer as well. So at the end, I know it takes more code since I have an extra class to wrap it and extra locales, but isn't sweet to first have it generic (per validation errors) and second to have multiple locale language easily?
Let's start this off with a short code snippet I will use to demonstrate my opinion:
$title = new Zend_Form_Element_Text('title', array(
'label' => 'Title',
'required' => false,
'filters' => array(
'StringTrim',
'HtmlEntities'
),
'validators' => array(
array('StringLength', false, array(3, 100))
),
));
This important line is:
'required' => false,
Which means that the input field is not required and you can submit the form without filling it. However, this also means that any filters and validators won't apply to it if you choose to fill in this field.
Common sense tells me that is an irrational behavior. The way I understand the word 'required' in relation with HTML input fields: an input field that is not required should return NULL if it is not filled in but if user decides to fill it both filters and validators should apply to it. That's what makes sense to me. Do you agree with me or is my common sense not so common?
Now more practical question, because this is how Zend_Form behaves, how can I achieve not required fields which would work as I described above (if nothing is typed in by user it returns NULL otherwise filters and validators normally apply).
Not really a complete answer to your question, but since comments don't have syntax formatting; here's a filter you can use to make your field values null if empty.
class My_Filter_NullIfEmpty implements Zend_Filter_Interface
{
public function filter( $value )
{
// maybe you need to expand the conditions here
if( 0 == strlen( $value ) )
{
return null;
}
return $value;
}
}
About the required part:
I'm not sure really. You could try to search the ZF mailinglists on Nabble:
http://www.nabble.com/Zend-Framework-Community-f16154.html
Or subscribe to their mailinglist, and ask them the question. Either through Nabble, or directly via the addresses on framework.zend.com:
http://tinyurl.com/y4f9lz
Edit:
Ok, so now I've done some tests myself, cause what you said all sounded counter intuitive to me. Your example works fine with me. This is what I've used:
<?php
class Form extends Zend_Form
{
public function init()
{
$title = new Zend_Form_Element_Text('title', array(
'label' => 'Title',
'required' => false,
'filters' => array(
'StringTrim',
'HtmlEntities',
'NullIfEmpty' // be sure this one is available
),
'validators' => array(
array('StringLength', false, array(3, 100))
),
));
$this->addElement( $title );
}
}
$form = new Form();
$postValues = array( 'title' => '' ); // or
$postValues = array( 'title' => ' ' ); // or
$postValues = array( 'title' => 'ab' ); // or
$postValues = array( 'title' => ' ab ' ); // or
$postValues = array( 'title' => '<abc>' ); // all work perfectly fine with me
// validate the form (which automatically sets the values in the form object)
if( $form->isValid( $postValues ) )
{
// retrieve the relevant value
var_dump( $form->getValue( 'title' ) );
}
else
{
echo 'form invalid';
}
?>
Actually, what you describe as your expectations are exactly how Zend_Form works. If you mark the element as not required, then the following happens: (a) if no value is passed, it skips validation, but if (b) a value is passed, then it must pass all validators in order to be valid.
BTW, best place to ask ZF questions is on the ZF mailing lists: http://framework.zend.com/archives