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.
Related
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?
i just write my first article so please tell me if i've done something wrong!
My Problem: I want to validate data given by url.
../Logs/requests?from=2011-10-18T16:15:00&to=2011-10-18T16:30:00&fmt=csv
I have just find out that there is an option to validate with the rules added to the Model.
public $validate = array(
'request_id' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
)
);
Using "ModelName->set($params)" in the Controller and after that the "ModelName->validates()"-function should deliver the answer if its valid or not. The only differenz between my solution and the solution at http://book.cakephp.org/2.0/en/models/data-validation/validating-data-from-the-controller.html
is that my controller using a couple of Models to collect the data for the response.
The problem is that the "validates()"-function just return "valid" even if i put in special-characters or other stuff what should be "not valid"-signed by the model-rules.
Help!
This is not an answer, but added to assist the OP;
I've created a test controller/model to test your situation. I deliberately did not extend the 'AppController' / 'AppModel' to remove any code in those from causing problems.
My test model (app/Model/Some.php)
class Some extends Model
{
public $name = 'Some';
public $useTable = 'false';
public $validate = array(
'request_id' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
)
);
}
My test controller (app/Controller/SomeController.php)
class SomeController extends Controller
{
public $uses = array('Some');
public function index()
{
$this->autoRender = false;
$params = array('Some' => array('request_id'=>'4*G/&2'));
$this->Some->set($params);
$result = $this->Some->validates();
debug($result);
$params = array('Some' => array('request_id'=>'AAAA'));
$this->Some->set($params);
$result = $this->Some->validates();
debug($result);
}
}
Outputs:
\app\Controller\SomeController.php (line 32)
false
\app\Controller\SomeController.php (line 37)
true
This test setup seems to work as planned, so you may try to test these in your application as well to narrow down the cause of your problem. Maybe some behavior is attached to your AppModel that contains a 'beforeValidate()' callback and disables the validation of the request_id field?
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?
I am slowly building up my Zend skills by building some utility websites for my own use. I have been using Zend Forms and Form validation and so far have been happy that I have been understanding the Zend way of doing things. However I am a bit confused with how to use Zend_Validate_Db_NoRecordExists() in the context of an edit form and a field that maps to database column that has to be unique.
For example using this simple table
TABLE Test
(
ID INT AUTO_INCREMENT,
Data INT UNIQUE
);
If I was simply adding a new row to the Table Test, I could add a validator to the Zend Form element for the Data field as such:
$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data') )
At form validation this validator will check that the contents of the Data element does not already exist in the table. Thus the insert into Test can go ahead without violating the Data fields UNIQUE qualifier.
However the situation is different when editing an existing row of the Test table. In that case the validator needs to check that the element value meets one of two mutually exclusive conditions conditions:
The user has changed the element value, and the new value does not currently
exist in the table.
The user has Not changed the element value. Thus the value does currently exist in the table (and this is OK).
The Zend Validation Docs talk about adding a parameter to the NoRecordExists() validator for the purpose of excluding records from the validation process. The idea being to "validate the table looking for any matching rows, but ignore any hits where the a field has this specific value". Such a use case is what is needed for the validating the element when editing a table. The pseudo code to do this in 1.9 is like so (actually I got this from the 1.9 source code - I think the current docs may be wrong):
$data = new Zend_Form_Element_Text('Data');
$data->addValidator( new Zend_Validate_Db_NoRecordExists('Test', 'Data',
array ('field'=>'Data', 'Value'=> $Value) );
The problem is that the value that is to be excluded ($Value) is bound to the validator at the time it is instantiated (also when the form is instantiated). But when the form is editing a record, that value needs to be bound to the contents of the $data field when the form was initially populated with data - IE the Data value initially read from the Test table row. But in typical Zend patterns a form is instantiated and populated in two separate steps which precludes binding the exclude value to the desired element value.
The following Zend psuedo code marks where I would like the binding of $Value to the NoRecordExists() validator to occur (and note that this is a common Zend controller pattern):
$form = new Form()
if (is Post) {
$formData = GetPostData()
if ($form->isValid($formData)) {
Update Table with $formData
Redirect out of here
} else {
$form->populate($formData)
}
} else {
$RowData = Get Data from Table
$form->populate($RowData) <=== This is where I want ('value' => $Value) bound
}
I could sub-class Zend_Form and override the populate() method to do a one-shot insertion of the NoRecordExists() validator on initial form population, but that seems like a huge hack to me. So I wanted to know what other people think and is there some pattern already written down that solves this problem?
Edit 2009-02-04
I've been thinking that the only decent solution to this problem is to write a custom validator and forget about the Zend version. My form has the record ID as hidden field, so that given the table and column names I could craft some SQL to test for uniqueness and exclude the row with an ID of such an such. Of course this started me thinking about how I would be tying the form to the dB layer that the Model is supposed to hide!
This is how it's done:
I your FORM, you add this validator (for example email field):
$email->addValidator('Db_NoRecordExists', true, array('table' => 'user', 'field' => 'email'));
Don't add custom error message for this since after that it didn't work for me, e.g.:
$email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');
In your Controller add this:
/* Don't check for Db_NoRecordExists if editing the same field */
$form->getElement('email')
->addValidator('Db_NoRecordExists',
false,
array('table' => 'user',
'field' => 'email',
'exclude' => array ('field' => 'id', 'value' => $this->request->get('id'))));
And after this you do verifications, e.g.:
if ($this->getRequest()->isPost())
{
if($form->isValid($this->getRequest()->getPost()))
{
....
That's it!
This will also work :
$this->addElement('text', 'email', array(
'label' => 'Your email address:',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
'EmailAddress',
array('Db_NoRecordExists', true, array(
'table' => 'guestbook',
'field' => 'email',
'messages' => array(
'recordFound' => 'Email already taken'
)
)
)
)
));
After reviewing the overwhelming response I've decided that I'm going with a custom validator
Look at this one:
Answer raised by me and well-solved by Dickie
private $_id;
public function setId($id=null)
{
$this->_id=$id;
}
public function init()
{
.....
if(isset($this->_id)){
$email->addValidator('Db_NoRecordExists', false, array('table' => 'user', 'field' => 'email','exclude' => array ('field' => 'id', 'value' => $this->_id) ));
$email->getValidator('Db_NoRecordExists')->setMessage('This email is already registered.');
}
Now u can use:
$form = new Form_Test(array('id'=>$id));
You could just call $form->getElement('input')->removeValidator('Zend_Validator_Db_NoRecordExists'); instead of supplying the exclusion.
I have just tried this example for email address uniqueness and it works perfectly with below stuffs :
1] In my form:
// Add an email element
$this->addElement('text', 'email', array(
'label' => 'Email :',
'required' => true,
'filters' => array('StringTrim'),
'validators' => array(
'EmailAddress',
)
));
Here's something special that I needed to add for unique email address to work:
$email = new Zend_Form_Element_Text('email');
$email->addValidator('Db_NoRecordExists', true, array('table' => 'guestbook', 'field' => 'email'));
2] In my controller:
$form->getElement('email')
->addValidator('Db_NoRecordExists',
false,
array('table' => 'guestbook',
'field' => 'email',
'exclude' => array ('field' => 'id', 'value' => $request->get('id'))));
if ($this->getRequest()->isPost()) {
if ($form->isValid($request->getPost())) {
Hope it helps you people !
Thanks