I have three phone fields (work_phone, home_phone and cell_phone). I would like to make sure that the user fills out at least one of them. This is my validation so far.
array(
'field' => 'work_phone',
'label' => 'lang:employee.work_phone',
'rules' => 'max_length[10]|numeric|callback_check_phones[work_phone]'
),
array(
'field' => 'home_phone',
'label' => 'lang:employee.home_phone',
'rules' => 'max_length[10]|numeric|callback_check_phones[home_phone]'
),
array(
'field' => 'cell_phone',
'label' => 'lang:employee.cell_phone',
'rules' => 'max_length[10]|numeric|callback_check_phones[cell_phone]'
),
function check_phones($value,$name) {
if((!isset($_POST[$name]))) {
$this->form_validation->set_message('check_phones',
'You must enter at least one phone number');
return FALSE;
}
else
{
return TRUE;
}
}
The problem is that it makes ALL the phone fields required. If I try if((!isset($_POST[work_phone])) ||(!isset($_POST[home_phone])) ){ no error is returned.
What's the best way to check if one of the three fields is not null?
EDIT
I got this to work by using empty() instead of isset() and && instead of || I know have
function check_phones($value){
if((empty($_POST['work_phone'])) && (empty($_POST['home_phone'])) && (empty($_POST['cell_phone']))){
$this->form_validation->set_message('check_phones', 'You must enter at least one phone number');
return FALSE;
}
else
{
return TRUE;
}
}
Which works but returns the error three times
just change your !isset statements to isset:
if(isset($_POST['phone1') || isset($_POST['phone2']) || isset($_POST['phone3'])){
//at least 1 is filled.
}else{
//fail
}
how about using the CI input class... $this->input->post will return a false if its empty
if($this->input->post('work_phone') || $this->input->post('home_phone') || $this->input->post('cell_phone'))
{
echo "We have your phone!";
}
else
{
echo "Please enter at least one!";
}
Update for CI's validation...
If they haven't filled in any phone field, you could just add validation for the first one. Like so...
if($_SERVER['REQUEST_METHOD'] == "POST")
{
if($this->input->post('work_phone') || $this->input->post('home_phone') || $this->input->post('cell_phone'))
{
echo "At least one is in there";
}
else
{
$this->form_validation->set_rules('work_phone', '1 Phone', 'required');
// echo "Please enter at least one!";
}
}
The answer is to use empty() instead of isset() see above.
Related
On the HTML form, I have a field such as:
<?php
$token = array(
'name' => 'pc_token',
'id' => 'pc_token',
'class' => 'form-control'
);
echo form_input($token, set_value('pc_token')); ?>
The validation rules set on the field are:
$this->form_validation->set_rules(
'pc_token', 'Token number', 'trim|required|min_length[5]|max_length[12]|callback_token_exists',
array(
'required' => 'You have not provided %s.',
'token_exists' => 'The %s is not valid. Please recheck again'
)
);
And here is the function for the callback
public function token_exists($key)
{
$this->load->model('tokens');
return $this->tokens->IsValidToken($key); // will return true if found in database or false if not found
}
The problem here is that when I keep the pc_token field empty/blank and submit the form, I don't get the expected error message printed on screen.
Current Output
The Token number is not valid. Please recheck again
Expected Output
You have not provided Token number
So why does CI ignore the previous rules (such as required, min_length etc) in this case? If my assumption is correct, the direction is left to right and if even one fails, it does not move to the next rule.
try this in your callback function
check for empty
public function token_exists($key='')
{
if(empty($key)){
$this->form_validation->set_message('token_exists', 'The {field} field is required.');
return FALSE;
}else{
$this->load->model('tokens');
return $this->tokens->IsValidToken($key);
}
// will return true if found in database or false if not found
}
I'll post the approach that I took. But I'll accept Abhishek's answer as he led me in the right direction. It's a bit sad that CI3 did not address it so I'm forced to use an alternate approach.
So, the validation rules become:
$this->form_validation->set_rules(
'pc_token', 'Token number', 'callback_token_exists'
);
And the callback function becomes:
public function token_exists($key)
{
if(trim($key) == "" || empty($key))
{
$this->form_validation->set_message('token_exists', 'You have not provided %s.');
return FALSE;
}
else if(strlen($key) < 5)
{
$this->form_validation->set_message('token_exists', '%s should be at least 5 characters long.');
return FALSE;
}
else if(strlen($key) > 12)
{
$this->form_validation->set_message('token_exists', '%s cannot be greater than 12 characters long.');
return FALSE;
}
else
{
$this->load->model('tokens');
$isValid = $this->tokens->IsValidToken($key);
if(! $isValid)
{
$this->form_validation->set_message('token_exists', 'You have not provided %s.');
}
return $isValid;
}
}
I want to pass multiple callbacks in codeigniter form validation rules.... but only one of the callbacks work
I am using this syntax in my contoller
$this->form_validation->set_rules(
array(
'field' => 'field_name',
'label' => 'Field Name',
'rules' => 'callback_fieldcallback_1|callback_fieldcallback_2[param]',
'errors' => array(
'fieldcallback_1' => 'Error message for rule 1.',
'fieldcallback_2' => 'Error message for rule 2.',
)
),
);
and the callback functions are....
function fieldcallback_1 (){
if(condition == TRUE){
return TRUE;
} else {
return FALSE;
}
}
function fieldcallback_2 ($param){
if(condition == TRUE){
return TRUE;
} else {
return FALSE;
}
}
Someone please help me out with this problem.... any other solutions regarding passing multiple callbacks in form validation rules are also appreciated...
All validation routines must have at least one argument which is the value of the field to be validated. So, a callback that has no extra arguments should be defined like this.
function fieldcallback_1($str){
return ($str === "someValue");
}
A callback that requires two arguments is defined like this
function fieldcallback_2 ($str, $param){
//are they the same value?
if($str === $param){
return TRUE;
} else {
$this->form_validation->set_message('fieldcallback_2', 'Error message for rule 2.');
//Note: `set_message()` rule name (first argument) should not include the prefix "callback_"
return FALSE;
}
Maybe like this?
$this->form_validation->set_rules(
array(
'field' => 'field_name',
'label' => 'Field Name',
'rules' => 'callback_fieldcallback_1[param]'),
);
// Functions for rules
function fieldcallback_1 ($param){
if(condition == TRUE){
return fieldcallback_2($param);
} else {
$this->form_validation->set_message('callback_fieldcallback_1', 'Error message for rule 1.');
return FALSE;
}
}
function fieldcallback_2 ($param){
if(condition == TRUE){
return TRUE;
} else {
$this->form_validation->set_message('callback_fieldcallback_1', 'Error message for rule 2.');
return FALSE;
}
}
I want to set these validation rule in CakePHP
Rule:
One of these fields is required but not both.
discount_percent
discount_amount
If discount_amount is input as 0 a NULL should be saved and then discount_percent is required to be > 1 but <=100.
If discount_percent is input a 0 then a NULL should be saved and then discount_amount is required to be > 0 but <= products.price for the selected product.
I have tried but not getting right way to perform this validation.
Modal Code:
App::uses('AppModel', 'Model');
class Code extends AppModel {
public $validate = array(
'discount_amount' => array(
'rule' => array('checkLimit'),
'message' => 'Please supply a valid discount_amount'
),
'discount_percent' => array(
'rule' => array('checkLimit'),
'message' => 'Please supply a valid discount_percent'
)
);
public function checkLimit($field) {
$passed = true;
if (isset($this->data[$this->alias]['discount_amount']) && empty($this->data[$this->alias]['discount_amount'])) {
??????
} else {
??????
}
}
}
Validation rules should not change any data!
So "if 0, save null" is not allowed in a validation rule.
You should implement that logic in a beforeSave() callback rather.
Regarding the validation, there is a second parameter provided containing all the $data you could use to validate other fields (and pull additional required data from the database - your product price probably).
Good documentation is at http://book.cakephp.org/2.0/en/models/data-validation.html#adding-your-own-validation-methods
Be careful using empty and isset, they're not exact opposites. empty('0') returns true, while isset('0') also return true. I think you want to use isset and !isset instead.
public function checkLimit($field) {
if ((!isset($this->data[$this->alias]['discount_amount']) && isset($this->data[$this->alias]['discount_percent'])) {
//only percent is set
if ($this->data[$this->alias]['discount_percent'] >= 1 && $this->data[$this->alias]['discount_percent'] <= 100) {
//percent is in correct range
return true;
}
} else if ((isset($this->data[$this->alias]['discount_amount']) && !isset($this->data[$this->alias]['discount_percent'])) {
//only amount is set
if ($this->data[$this->alias]['discount_amount'] >= 0 && $this->data[$this->alias]['discount_amount'] <= $products.price) {
//amount is in correct range
return true;
}
}
//either neither or both fields are set, or values aren't in correct range
return false;
}
I'm trying to create a custom validation rule for when a checkbox is checked, an input field will need to be filled out in order to proceed to the next page. If unchecked, the input field will not be required.
Here's my code in View:
echo $this->Form->inputs(array(
'legend'=>'Certifications',
'rn_box'=>array(
'type'=>'checkbox',
'label'=>'RN',
'value' => $results['Education']['rn_box']
),
'rn_number'=>array(
'label'=>'RN Number:',
'value' => $results['Education']['rn_number']
),
));
In my Model I created a function:
public function rnCheck () {
if ($this->data['Education']['rn_box'] == '0') {
return false;
}
return true;
}
public $validate = array(
'rn_number' => array(
'rnCheck'=>array(
'rule'=>'rnCheck',
'message'=>'Please Provide a Number'
),
),
);
The checkbox returns a value of 1 if checked, and a value of 0 unchecked. The rn_number field is an input field that I'm trying to validate. I tried playing with 'required', 'allowEmpty', etc. with no luck. If anyone can point me in the right direct, that would be great, thanks!
You can probably just handle it all in the function callback for rn_number. I would also call the function and rule name rn_number to avoid any confusion.
For example, change your validate array to:
public $validate = array(
'rn_number' => array(
'rn_number'=>array(
'rule'=>'rn_number'
),
),
);
And then your custom validation function can look like:
public function rn_number () {
if ($this->data['Education']['rn_box'] == 1) {
if($this->data['Education']['rn_number'] == '')
$errors[] = "Please enter your RN Number.";
}
if (!empty($errors))
return implode("\n", $errors);
return true;
}
I'm handling the error message in the custom validation function - not in the validate array. Let me know if this doesn't work!
I am pretty sure that I have just missed something very obvious but to my eyes I cannot work out what. The empty form validation is working correctly but its when I enter any random values into the input boxes and click login it shows 'This is working fine'; so I have a feeling that it is something to do with my callback function.
I am trying to make is so the person can login with their username or password
Validation:
'loginUser' => array(
array(
'field' => 'userLoginUsername',
'label' => 'Username',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'userLoginPassword',
'label' => 'Password',
'rules' => 'trim|required|callback__check_login|xss_clean|sha1'
)
)// End of login user array
Callback:
function _check_login($username, $password)
{
if($this->users_model->login_check($username,$password))
{
$this->form_validation->set_message('_check_login', 'Sorry you have entered an incorrect %s ');
return FALSE;
}else{
return TRUE;
}
}
Controller:
function login()
{
if($this->form_validation->run('loginUser') == FALSE)
{
$data['success'] = '';
}else{
echo 'This is working fine';
}
$data['companyName'] = $this->core_model->companyDetails()->coreCompanyName;
$data['pageTitle'] = "User Login";
$this->load->view('frontend/assets/header', $data);
$this->load->view('frontend/user_login', $data);
$this->load->view('frontend/assets/footer');
}
}
Model:
function login_check($username, $password)
{
$this->db->select('userName,userEmail,userPassword');
$this->db->from('users');
$this->db->where('userName', $username, 'userEmail', $username, 'userPassword' , $password, 'userActive', 1);
$query = $this->db->get();
if($query->num_rows() == 1)
{
return TRUE;
}else{
return FALSE;
}
}
View:
<h1><?php echo $companyName; echo nbs(1);?> - <?php echo $pageTitle; ?></h1>
<div class="formComments">
<p class="error"><?php echo validation_errors();?></p>
<p class="success"><?php echo $this->session->flashdata('success'); ?></p>
</div>
<div class="user_login">
<form class="form-inline" method="POST" action="login" >
<input type="text" name="userLoginUsername" id="userLoginUsername" class="input-small" placeholder="Username">
<input type="password" name="userLoginPassword" id="userLoginPassword" class="input-small" placeholder="Password">
<button type="submit" class"btn">Login</button>
</form>
</div>
in your code
if data is verified by model ie TRUE returned callback _check_login will return FALSE to login() because of
if($this->users_model->login_check($username,$password))
{
$this->form_validation->set_message('_check_login', 'Sorry you have entered an incorrect %s ');
return FALSE;
}
hence condition
if($this->form_validation->run('loginUser') == FALSE)
will be succeeded and it will set $data['success'] = '';
for wrong input or empty validation model returns FALSE so
if($this->users_model->login_check($username,$password))
{
$this->form_validation->set_message('_check_login', 'Sorry you have entered an incorrect %s ');
return FALSE;
}else{
return TRUE; /* login check failed control comes here*/
}
hence
if($this->form_validation->run('loginUser') == FALSE)
{
$data['success'] = '';
}else{
echo 'This is working fine'; /*control comes here now*/
}
change
if($this->users_model->login_check($username,$password))
to
if(!$this->users_model->login_check($username,$password))
and it should work
hope this helps
EDIT__
well, just figured out something you are missing might be creating the issue. the callback you are setting in the rule array
array(
'field' => 'userLoginPassword',
'label' => 'Password',
'rules' => 'trim|required|callback__check_login['.$_POST['userLoginUsername'].']|xss_clean|sha1'
)
must be
array(
'field' => 'userLoginPassword',
'label' => 'Password',
'rules' => 'trim|callback__check_login['.$_POST['userLoginUsername'].']|xss_clean|sha1'
)
because the callback function is expecting 2 values and the way you are using it only send password field to it. also with this rearrange the callback argument to
function _check_login($password, $username)
so the first value be password and second be username. for checking 'userActive' remove it from the where clause and check its value if query returned some record
if($query->num_rows() == 1){
/* check its value if 1 do something as you asked in comment*/
Ok, that's a lot of code but I spotted this:
In your controller you use a validation rule to check for the right user data; besides that I wouldn't do like that, since properly speaking it isn't a "form validation" rule, what I see is that if your user exists and his credentials are correct you return TRUE.
That's fine, but in your validation rule you have:
if($this->users_model->login_check($username,$password))
{
$this->form_validation->set_message('_check_login', 'Sorry you have entered an incorrect %s ');
return FALSE;
which measn that when the model returns TRUE (user is ok), your validation returns FALSE! and that means when the user is right your validation doesn't succeed, and when your user is "wrong" (see your "random input") the rule returns TRUE, making it a success.
I don't have time to look further now, but skimming the code everything looks ok apart from this. SO, just change that line to
if(!$this->users_model->login_check($username,$password))
{
i.e. "if the model returns FALSE, make the rule return FALSE too". Hope it is clear.
It looks like this line here:
if($this->form_validation->run('loginUser') == FALSE)
You should either remove 'loginUser' or pop in a variable, like $loginUser, something feels funny about your array.