I have two numeric fields to collect data from users. Need to validate it using codeigniter form validation class.
Conditions:
First field can be zero
Second field cannot be zero
First field should not be equal to second field
Second field should be greater than first field
Currently I use
$this->form_validation->set_rules('first_field', 'First Field',
'trim|required|is_natural');
$this->form_validation->set_rules('second_field', 'Second Field',
'trim|required|is_natural_no_zero');
But, how to validate for 3rd and 4th condition mentioned above?
Thanks in advance.
Thanks dm03514. I got it working by the below callback function.
$this->form_validation->set_rules('first_field', 'First Field', 'trim|required|is_natural');
$this->form_validation->set_rules('second_field', 'Second Field', 'trim|required|is_natural_no_zero|callback_check_equal_less['.$this->input->post('first_field').']');
and the callback function is:
function check_equal_less($second_field,$first_field)
{
if ($second_field <= $first_field)
{
$this->form_validation->set_message('check_equal_less', 'The First &/or Second fields have errors.');
return false;
}
return true;
}
Everything seems to be working fine now :)
You can write your own validation function for 3, and 4 using callbacks
http://ellislab.com/codeigniter/user-guide/libraries/form_validation.html#callbacks
Example from doc
<?php
class Form extends CI_Controller {
public function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|is_unique[users.email]');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
public function username_check($str)
{
if ($str == 'test')
{
$this->form_validation->set_message('username_check', 'The %s field can not be the word "test"');
return FALSE;
}
else
{
return TRUE;
}
}
}
?>
If you are using HMVC and the accepted solution doesn't work then
add the following line after initialization in your controller
$this->form_validation->CI =& $this;
So it will be
$this->load->library('form_validation');
$this->form_validation->CI =& $this;
in your controller.
Related
I need to compare 2 attribute value in the model and only if first value is lower than second value form can validate.I try with below code but it not worked.
controller
public function actionOpanningBalance(){
$model = new Bill();
if ($model->load(Yii::$app->request->post())) {
$model->created_at = \Yii::$app->user->identity->id;
$model->save();
}else{
return $this->render('OpanningBalance', [
'model' => $model,
]);
}
}
Model
public function rules()
{
return [
[['outlet_id', 'sr_id', 'bill_number', 'bill_date', 'created_at', 'created_date','bill_amount','credit_amount'], 'required'],
[['outlet_id', 'sr_id', 'created_at', 'updated_at'], 'integer'],
[['bill_date', 'd_slip_date', 'cheque_date', 'created_date', 'updated_date','status'], 'safe'],
[['bill_amount', 'cash_amount', 'cheque_amount', 'credit_amount'], 'number'],
[['comment'], 'string'],
['credit_amount',function compareValue($attribute,$param){
if($this->$attribute > $this->bill_amount){
$this->addError($attribute, 'Credit amount should less than Bill amount');
}],
[['bill_number', 'd_slip_no', 'bank', 'branch'], 'string', 'max' => 225],
[['cheque_number'], 'string', 'max' => 100],
[['bill_number'], 'unique']
];
}
}
It's going in to the validator function but not add the error like i wanted
$this->addError($attribute, 'Credit amount should less than Bill amount');
anyone can help me with this?
If the validation is not adding any error, it's most likely being skipped. The issue is most likely becasue of default rules behaviour whereby it skips empty or already error given values as per here: https://www.yiiframework.com/doc/guide/2.0/en/input-validation#inline-validators
Specifically:
By default, inline validators will not be applied if their associated attributes receive empty inputs or if they have already failed some validation rules. If you want to make sure a rule is always applied, you may configure the skipOnEmpty and/or skipOnError properties to be false in the rule declarations.
So you would need to set up the skipOnEmpty or skipOnError values depending on what works for you:
[
['country', 'validateCountry', 'skipOnEmpty' => false, 'skipOnError' => false],
]
Try this:
public function actionOpanningBalance(){
$model = new Bill();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->created_at = \Yii::$app->user->identity->id;
$model->save();
}else{
return $this->render('OpanningBalance', [
'model' => $model,
]);
}
}
For Validation
You can use anonymous function :
['credit_amount',function ($attribute, $params) {
if ($this->$attribute > $this->bill_amount)) {
$this->addError($attribute, 'Credit amount should less than Bill amount.');
return false;
}
}],
you can use like this below answer is also write
public function rules(){
return [
['credit_amount','custom_function_validation', 'on' =>'scenario'];
}
public function custom_function_validation($attribute){
// add custom validation
if ($this->$attribute < $this->cash_amount)
$this->addError($attribute,'Credit amount should less than Bill amount.');
}
I've made custom_function_validation working using 3rd params like this:
public function is18yo($attribute, $params, $validator)
{
$dobDate = new DateTime($this->$attribute);
$now = new DateTime();
if ($now->diff($dobDate)->y < 18) {
$validator->addError($this, $attribute, 'At least 18 years old');
return false;
}
}
This is a back end validation and it will trigger on submit only. So you can try something like this inside your validation function.
if (!$this->hasErrors()) {
// Your validation code goes here.
}
If you check the basic Yii2 app generated you can see that example in file models/LoginForm.php, there is a function named validatePassword.
Validation will trigger only after submitting the form.
I have a list of checkboxes, which aren't associated with the model itself like the rest of the form:
echo Html::checkboxList('options', $selected_options, $options, ['class' => 'checkbox']);
In the model I have a following rules:
public function rules() {
return [
....*/
[['options'], 'integer'],
['options', 'optValidation', 'on' => 'update'],
];
}
And the following validator:
public function optValidation($attribute, $params) {
foreach ($attribute as $attr){
if ($attr == 1) {
$return = true;
}
else {
$return = false;
}
}
if (!$return) {
$this->addError($attribute, 'At least one checkbox has to be selected!');
}
}
Unfortunately nothing happens when submitting the form as if there are no rules for validation of the field 'options'. Where's the catch?
You need to add options as a public attribute inside your model class. Then you need to set it as safe inside your rules:
public function rules() {
...
[['options'], 'integer'],
[['options'], 'optValidation', 'on' => 'update'],
[['options'], 'safe'],
...
Finally, you will have to generate the input just like other inputs related to your model, even if it doesn't exist in your DB table, you need it inside your model:
<?php echo $form->field($model, 'options')->checkboxList('options', $selected_options, $options, ['class' => 'checkbox']); ?>
On my codeigniter project my callback is not working as would like with my multidimensional array post
I am trying on my callback set message $key['image'] to display correct value of the multidimensional array post. But when I var dump it returns NULL
On my set rules the multidimensional array validation works.
But for some reason the $key['image'] on my callback function
set_message('banner_image_regex', 'This banner' .' '. $key['image'] .' '. 'image contains a underscore cannot upload file.') not picking up.
Question on my callback function banner_image_regex() how can I make $key['image'] pick up the post value and display it.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Banner_add extends MX_Controller {
public function __construct() {
parent::__construct();
}
public function index() {
$data['title'] = "Banner Add";
$this->load->library('form_validation');
$this->form_validation->set_rules('banner_name', 'Banner Name', 'required|callback_validate_form');
$this->form_validation->set_rules('banner_status', 'Banner Status', 'required');
if (!empty($this->input->post('banner_image'))) {
foreach ($this->input->post('banner_image') as $key => $value) {
$this->form_validation->set_rules('banner_image['.$key.'][image]', 'Banner Image', 'callback_banner_image_regex');
}
}
if ($this->form_validation->run($this) == FALSE) {
$this->load->view('template/banner/banner_add', $data);
} else {
redirect('admin/banner/banner_list');
}
}
public function banner_image_regex() {
$banner_image = $this->input->post('banner_image');
foreach ($banner_image as $key => $value) {
if (preg_match('/^[a-z0-9]+$/', $key['image'])) {
return TRUE;
} else {
$this->form_validation->set_message('banner_image_regex', 'This banner' .' '. $key['image'] .' '. 'image contains a underscore cannot upload file.');
return FALSE;
}
}
}
}
Asuming you were following CI specs about naming array fields in form validation,
you are already sending specific value (string/image name) to callback function.
So it need to be like:
public function banner_image_regex($image_name) {
if (preg_match('/^[a-z0-9]+$/', $image_name)) {
return TRUE;
} else {
$this->form_validation->set_message('banner_image_regex', 'This banner' .' '. $image_name .' '. 'image contains a underscore cannot upload file.');
return FALSE;
}
}
I am using uri segment to delete info in my database:
anchor('site/delete_note/'.$row->id, 'Delete')
Model:
function delete_note()
{
$this->db->where('id', $this->uri->segment(3));
$this->db->delete('note');
}
It works fine, but I want to do the same for updating my info and can't get it work
So this is link in view:
anchor('site/edit_note/'.$row->id, 'Edit')
My controller:
function edit_note()
{
$note_id = $this->uri->segment(3);
$data['main_content'] = 'edit_note';
$this->load->view('includes/template', $data);
$this->load->library('form_validation');
$this->form_validation->set_rules('content', 'Message', 'trim|required');
if($this->form_validation->run() == TRUE)
{
$this->load->model('Note_model');
$this->Note_model->edit_note($note_id);
redirect('site/members_area');
}
}
My model:
function edit_note($note_id)
{
$content = $this->input->post('content');
$data = array('content' => $content);
$this->db->where('id', $note_id);
$this->db->update('note', $data);
}
My view of edit_note:
<?php
echo form_open('site/edit_note');
echo form_textarea('content', set_value('content', 'Your message'));
echo form_submit('submit', 'Change');
echo anchor('site/members_area', 'Cancel');
echo validation_errors('<p class="error">'); ?>
Edit doesn't work as delete, when i am trying to get segment directly in edit model, as I used in delete model.
If I set $note_id to a number in my controller, instead of this '$this->uri->segment(3)', it updates my database. But if I use getting segment it doesn't work. I thought uri segments are available in controller as in model, but there is something I don't know.
Better yet, instead of manually reading the IDs via the segments, you could change your functions to be:
function delete_note($note_id)
and
function edit_note($note_id)
And remove the $note_id = $this->uri->segment(3); lines.
And as silly as it'll sound, the generated URL is definitely correct, right?
And last question, have you done anything with routes?
Edit
I've also noticed that in edit, you use this in your form:
echo form_open('site/edit_note');
So when the form submits, the URL it submits to is site/edit_note instead of site/edit_note/{SOME_ID}. So once you make your changes, and the form submits, there won't be a 3rd URL segment!
Well there are some logical errors in your code.
function edit_note()
{
$note_id = $this->uri->segment(3);
$data['main_content'] = 'edit_note';
$this->load->view('includes/template', $data);
//// What is the use of loadig a view when you are editing
$this->load->library('form_validation');
$this->form_validation->set_rules('content', 'Message', 'trim|required');
if($this->form_validation->run() == TRUE)
{
$this->load->model('Note_model');
$this->Note_model->edit_note($note_id);
redirect('site/members_area');
}
}
Instead do it like this
function edit_note()
{
if($this->input->post()){
$this->load->library('form_validation');
$this->form_validation->set_rules('content', 'Message', 'trim|required');
if($this->form_validation->run() == TRUE)
{
$this->load->model('Note_model');
$this->Note_model->edit_note($note_id);
redirect('site/members_area');
}
}else{
$note_id = $this->uri->segment(3);
$data['main_content'] = 'edit_note';
$this->load->view('includes/template', $data);
}
}
MOST IMPORTANT
And the other thing you should note that you are using anchor to access edit note but not actually submitting a form so it is not getting any post data to update.
In my view it's a 'bad' approach to use uri segments in your models... you should pass an id as a parameter from your controller functions ..
function delete_note()
{
$this->db->where('id', $this->uri->segment(3));
$this->db->delete('note');
}
What if you want to re-use this delete method? e.g. deleting notes from an admin panel, via a cron job etc then the above relies upon the uri segment and you will need to create additional delete methods to do the job. Also, if you were to continue with the same you don't even need a model then .. just call these lines in your controllers if you know what I mean ...
$this->db->where('id', $this->uri->segment(3));
$this->db->delete('note');
so best is to change it to similar to your edit_note() model function.
Please please please can someone help me
$this->load->library('form_validation');
$this->load->helper('cookie');
$data = array();
if($_POST) {
// Set validation rules including additional validation for uniqueness
$this->form_validation->set_rules('yourname', 'Your Name', 'trim|required');
$this->form_validation->set_rules('youremail', 'Your Email', 'trim|required|valid_email');
$this->form_validation->set_rules('friendname', 'Friends Name', 'trim|required');
$this->form_validation->set_rules('friendemail', 'Friends Email', 'trim|required|valid_email');
// Run the validation and take action
if($this->form_validation->run()) {
echo 'valid;
}
}
else{
echo 'problem';
}
Form validation is coming back with no errors can cany one see why?
Is it actually echoing 'valid'? (you're missing an apostrophe there, btw)
The code you show will only echo 'problem' when $_POST is false, not when validation fails.
Without knowing more, it may be as simple as:
// Run the validation and take action
if($this->form_validation->run()) {
echo('valid');
} else {
echo('invalid');
}
Try like this without checking if $_POST is set - not really needed:
//validation rules here
//
if ($this->form_validation->run() == TRUE) {
//do whatever that shall be run on succeed
} else {
$this->load->view('form'); //load the form
}
Read more about the controller part here