Cakephp validation issue - validation

Hey guys got an issue with Cakephp validation..
I want to know why is partytwo validation going straight to false?
Here is my Relationship model:
<?php
class Relationship extends AppModel{
var $name='Relationship';
public $useTable = 'relationships_users';
public $primaryKey = 'id';
var $validate = array(
'date' => array(
'rule' => array('datevalidation', 'systemDate'),
'message' => 'Current Date and System Date is mismatched'
),
'partytwo'=>array(
'partytwoExists'=>array(
'rule'=> 'userExists',
'message'=>'That username doesnt exist.'
)
)
);
function datevalidation( $field=array(), $compare_field=null ) {
if ($field['date'] > $compare_field)
return TRUE;
else
return FALSE;
}
function userExists($check) {
$userExists= $this->find('count', array('conditions'=>$check));
if($userExists == 1) {
return TRUE;
}else{
return FALSE;
}
}
...

According to the CakePHP book Adding Your Own Validation Methods section, a custom rule that wrote like this
'rule' => array('datevalidation', 'systemDate')
means Cake will runs your datevalidation method like this:
$valid = $Relationships->datevalidation(array(
'date' => 'some user input value'
), 'systemDate');
With the same fashion,
'rule' => array('userExists')
causes Cake to run
$valid = $Relationships->userExists(array(
'partytwo' => 'some user input value'
));
(Simulated calls. Actual calling is using dispatchMethod at line 3155 of Model.php)
So you are most probably need to rewrite your datevalidation method. Furthermore, your code
$userExists= $this->find('count', array('conditions'=>$check));
$userExists can return you a number larger or equal to 0. Your logic is wrong if it returns 2 or more. Consider Model::hasAny instead. It could be the reason why it is always validated as false for your case.

Related

Validating third variable on difference between 2 other variables in cakephp

I can't get my head around this one. I want to validate whether a third variable on a cakephp form is less than or equal to the difference between two other variables on the form. Has anyone tackled this or similar?
Paul
here is some code to show what I have done:
public function lessThanEqualTo($check, $otherfield) {
$value = array_values($check);
$compareTo = $this->data[$this->name][$otherfield];
if (!Validation::comparison($value[0], 'lessorequal', $compareTo)) {
return false;
}
else {
return true;
}
}
public function numDifference($startnumber, $usednumber) {
$sn = int($this->data[$this->name][$startnumber]);
$un = int($this->data[$this->name][$usednumber]);
return ($sn - $un);
}
Model contains validation: but the second rule is plain wrong, I have tried a number of things, but I am just coming up with rubbish:
public $validate = array(
'ag1_compl_dist_num'=>array(
'rule' => array('lessThanEqualTo','ag1_compl_start_number'),
'message' => 'Value must be less than starting number',
'allowEmpty' => true,
'required' => false
),
'ag1_compl_remain' => array(
'rule' => array('lessThanEqualTo','numDifference'),
'message' => 'Value must be less than difference between numbers',
'allowEmpty' => true,
'required' => false
)
);
Clearly, the call to numDifference should have something that identifies which two numbers to work out the difference between..
When you do:
'rule' => array('lessThanEqualTo','numDifference')
And then in your lessThanEqualTo function $compareTo = $this->data[$this->name][$otherfield];, you will look for numDifference field in your data object, which does not exist.
One way would be to create a lessThanEqualToDiff method like this:
public function lessThanEqualToDiff ($check, $startfield, $usedfield) {
$value = array_values($check);
$sn = intval($this->data[$this->name][$startfield]);
$un = intval($this->data[$this->name][$usedfield]);
return Validation::comparison($value[0], 'lessorequal', $sn - $un) ;
}
Then your rule:
public $validate = array(
'ag1_compl_remain' => array(
'rule' => array('lessThanEqualToDiff', 'ag1_compl_start_number', 'ag1_compl_used_number'),
'message' => 'Value must be less than difference between numbers',
'allowEmpty' => true,
'required' => false
)
);
So, the validation method should be like this:
public function lessThanEqualToDiff ($check, $startfield, $usedfield) {
$value = array_values($check);
$sn = (int)$this->data[$this->name][$startfield];
$un = (int)$this->data[$this->name][$usedfield]
return Validation::comparison($value[0], 'lessorequal', $sn - $un) ;
}
to use the php int feature correctly. Thanks to Holt and marian0 for their help.

Adding custom message to Zend Framework 2 Callback Validator

I would like to add a custom error message to my Callback Validator below ("Zip Code is required" for example), how would I go about doing this?
$zip = new \Zend\InputFilter\Input('zip');
$zip->setRequired(false);
$zip->getValidatorChain()
->attach(new \Zend\Validator\Callback(function ($value, $context) {
if($context['location_type_id'] == \Application\Model\ProjectModel::$LOCATION_TYPE_ID_AT_AN_ADDRESS)
{
return (isset($value)&&($value!= NULL))? $value: false;
}
return true;
}));
If you need more information, let me know and I will update.
Thanks for your help!
Abor
Just to throw in my two cents, a custom message can also be set via configuration. I often use this when using a factory type approach like so:
'name' => array(
...
'validators' => array(
new \Zend\Validator\Callback(
array(
'messages' => array(\Zend\Validator\Callback::INVALID_VALUE => '%value% can only be Foo'),
'callback' => function($value){
return $value == 'Foo';
}))
)
),
This produces a message like "Bar can only be Foo".
Look closely at the \Zend\Validator\Callback::INVALID_VALUE key, this is a constant defined in \Zend\Validator\Callback:
const INVALID_VALUE = 'callbackValue';
Which is used in that class to set the messages used by the validator:
protected $messageTemplates = array(
self::INVALID_VALUE => "The input is not valid",
self::INVALID_CALLBACK => "An exception has been raised within the callback",
);
Which means you can safely use \Zend\Validator\Callback::INVALID_VALUE => 'Custom message'
I'm not sure whether this breaks a coding principle, somebody please correct me if it does.
You can do it that way :
$callback = new \Zend\Validator\Callback(function ($value) {
// Your validation logic
}
);
$callback->setMessage('Zip Code is required');
$zip = new \Zend\InputFilter\Input('zip');
$zip->setRequired(false);
$zip->getValidatorChain()->attach($callback);
Thanks to jchampion for his help.
$zip = new \Zend\InputFilter\Input('zip');
$zip->setRequired(false);
$callback = new \Zend\Validator\Callback(function ($value, $context) {
if($context['location_type_id'] == \Application\Model\ProjectModel::$LOCATION_TYPE_ID_AT_AN_ADDRESS)
{
return (isset($value)&&($value!= NULL))? true: false;
}
return true;
});
$callback->setMessage('Zip Code is required');
$zip->getValidatorChain()->attach(new \Zend\Validator\NotEmpty(\Zend\Validator\NotEmpty::NULL));
$zip->getValidatorChain()->attach($callback);

Setting an Error Message located in language file

In a form I have a callback function that checks if a number is_available.
If it returns TRUE it shows an error message.
The callback is working but it displays : lang:shortcodes.not_unique instead of the content given in a separate file.
I can't figure out what is wrong and didn't find about that in the user guide.
Thank you for your help.
public function __construct()
{
parent::__construct();
// Load all the required classes
$this->load->model('shortcodes_m');
$this->load->library('form_validation');
$this->lang->load('shortcodes');
// Set the validation rules
$this->item_validation_rules = array(
array(
'field' => 'number',
'label' => 'lang:shortcodes.number',
'rules' => 'trim|max_length[100]|required|numeric'
),
array(
'field' => 'name',
'label' => 'lang:shortcodes.name',
'rules' => 'trim|max_length[100]|required|callback_shortcodes_check'
)
);
}
public function shortcodes_check($str)
{
if($this->shortcodes_m->is_available($str) == TRUE)
{
$this->form_validation->set_message('shortcodes_check','lang:shortcodes.not_unique');
return FALSE;
}
else
{
return TRUE;
}
}
You need to fetch the line from the language file. The docs don't make any mention of being able to use field name translation with the set_message() method. Use:
$this->lang->line('not_unique');

cakephp custom validation does not display error message in the nested rule

im doing a custom validation but it does not display error message when invalidated.
do you know where is the problem? I think the problem might be in the invalidate function. do you know how to set it up for the nested validation like this one?
var $validate = array(
'receiver' => array(
'maxMsg' => array(
'rule' => array('maxMsgSend'),
//'message' => ''
),
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'field must not be left empty'
))......
custom validation method in the model:
function maxMsgSend ( $data )
{
$id = User::$auth['User']['id'];
$count_contacts = (int)$this->Contact->find( 'count', array( 'conditions' =>array( 'and' =>array( 'Contact.contact_status_id' => '2',
'Contact.user_id' => $id))));
$current_credit = (int)$this->field( '3_credit_counter', array( 'id' => $id));
$max_allowed_messages = ($count_contacts >= $current_credit)? $current_credit: $count_contacts ;
if ($data>$max_allowed_messages)
{
$this->invalidate('maxMsg', "you can send maximum of {$max_allowed_messages} text messages.");
}
}
UPDATE: how is solved it.
i moved the the guts of the function to beforeValidate() in the model.
function beforeValidate($data) {
if (isset($this->data['User']['receiver']))
{
$id = User::$auth['User']['id'];
$count_contacts = (int)$this->Contact->find( 'count', array( 'conditions' =>array( 'and' =>array( 'Contact.contact_status_id' => '2',
'Contact.user_id' => $id))));
$current_credit = (int)$this->field( '3_credit_counter', array( 'id' => $id));
$max_allowed_messages = ($count_contacts >= $current_credit)? $current_credit: $count_contacts ;
if ($data>$max_allowed_messages)
{
$this->invalidate('receiver', "you can send maximum of {$max_allowed_messages} text messages.");
return false;
}
}
return true;
}
I think your maxMsgSend function still needs to return false if validation fails.
I think the problem is in your Model::maxMsgSend function. As written in the bakery, (http://bakery.cakephp.org/articles/view/using-equalto-validation-to-compare-two-form-fields), to build a custom validation rule (they want to compare two fields, but the concepts are the same), they write:
I return a false if the values don't match, and a true if they do.
Check out their code for the Model class, about half way down. In short, you don't need to call invalidate from within the custom validation method; you simply return true if it passes validation, and false if it doesn't pass validation.

CakePHP model validation with array

I want to use CakePHP's core validation for lists in my model:
var $validate = array(
'selectBox' => array(
'allowedChoice' => array(
'rule' => array('inList', $listToCheck),
'message' => 'Enter something in listToCheck.'
)
)
);
However, the $listToCheck array is the same array that's used in the view, to populate a selectbox. Where do I put this function?
public function getList() {
return array('hi'=>'Hello','bi'=>'Goodbye','si'=>'Salutations');
}
Already in my controller, in one of the actions I'm setting it for the view, like:
public function actionForForm() {
$options = $this->getList();
$this->set('options', $options);
}
So, I don't want to have to copy the getList() function...where can I put it so the Model can call it to populate its $listToCheck array?
Thanks for your help.
Considering that it's data, you should store the list of valid choices in the model.
class MyModel extends AppModel {
var $fieldAbcChoices = array('a' => 'The A', 'b' => 'The B', 'c' => 'The C');
}
You can get that variable in the Controller simply like this:
$this->set('fieldAbcs', $this->MyModel->fieldAbcChoices);
Unfortunately you can't simply use that variable in the rule declaration for the inList rule, since rules are declared as instance variables and those can only be initialized statically (no variables allowed). The best way around that is to set the variable in the Constructor:
var $validate = array(
'fieldAbc' => array(
'allowedChoice' => array(
'rule' => array('inList', array()),
'message' => 'Enter something in listToCheck.'
)
)
);
function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->validate['fieldAbc']['allowedChoice']['rule'][1] = array_keys($this->fieldAbcChoices);
}
If you're not comfortable overriding the Constructor, you could also do this in a beforeValidate() callback.
Also note that you shouldn't name your field 'selectBox'. :)

Resources