Codeigniter form validation unexpected behavior - php

I have classic CI controller and index method, in the method I'm trying to validate a very simple form entry.
public function index() {
$this->form_validation->set_rules('status', 'Status', 'trim');
if($this->form_validation->run()) {
echo "true";
$quote = array(
'status' => $this->input->post('status'),
'text' => $this->input->post('text'),
'author' => $this->input->post('author'),
);
$this->quote_model->add($quote);
set_flash_message('Quote has been added.', 'success');
redirect('quote');
}
else {
echo "false";
}
//Some other stuff
For some reason every time I submit the form method $this->form_validation->run() returns FALSE and thus code ends up echoing "false". BUT the quote is added to my database as well as 'Quote has been added.' flash message appears, which means the TRUE part of the condition somehow gets executed.
Has anyone ever encountered this issue? I have no idea what could be going on.

public function index() {
if ($this->input->post()) {
$this->form_validation->set_rules('status', 'Status', 'trim');
if ($this->form_validation->run()) {
echo "true";
$quote = array(
'status' => $this->input->post('status'),
'text' => $this->input->post('text'),
'author' => $this->input->post('author'),
);
$this->quote_model->add($quote);
set_flash_message('Quote has been added.', 'success');
redirect('quote');
} else {
echo "false";
}
} else {
$this->load->view("quote", $data);
}
}

Related

CI3 / Validation always returns false upon initial load

I do not understand why upon load the validation always returns false. Here is part of my controller:
// load up the validation rules for blog Info form
$this->config->load('mh_blog_validate');
$this->form_validation->set_rules($this->config->item('validate_blog_update'));
if ($this->form_validation->run('validate_blog_update') === FALSE) {
$errors = array('message' => $this->upload->display_errors());
$message = array('message' => 'Warning - '.$errors['message'],
'class' => 'danger',
);
$this->data['alert'] = bootstrap_alert($message);
}
Here is my validation config from mh_blog_validate:
$config['validate_blog_update'] = array(
'title' => array(
'field' => 'title',
'label' => '',
'rules' => 'required|trim|xss_clean|min_length[5]|callback_is_slug_unique_on_update[]',
'errors' => array(
'required' => 'The title cannot be blank.',
'min_length' => 'The title must be 5 charaters or more.',
'is_unique' => 'The title must be unique.',
'is_slug_unique_on_update' => 'The new title needs to be unique'
),
),
'body' => array(
'field' => 'body',
'label' => '',
'rules' => 'required|trim|xss_clean|min_length[5]',
'errors' => array(
'required' => 'The body cannot be blank',
'min_length' => 'The body must be 5 charaters or more.',
)
),
); // end validate_blog_create
This is the callback function I use in the validate:
function is_slug_unique_on_update() {
$new_slug = url_title($this->input->post('title'));
if ( $new_slug == $this->input->post('slug')) {
// no change in slug so update
// echo "no change in title";
return TRUE;
} elseif ( $new_slug !== $this->input->post('slug')) {
// new slug
$result = $this->Blog_model->is_slug_unique_on_update($new_slug);
return $result; // returns FALSE if the title is not unique
}
}
The output I receive in the view is "Warning - " and this is placed in the view:
if (isset($this->data['alert']){
echo $this->data['alert'];
}
I was expecting the validation not to produce an error because I have not submitted the form. It runs the validation maybe(?) even when I have not submitted the form I think.
+++ new edit +++
Added code below that works and wish to know why mine code doesn't. I thought my code follows the same pattern, no?
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', 'required');
$this->form_validation->set_rules('password', 'Password', 'required',
array('required' => 'You must provide a %s.')
);
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
$this->form_validation->set_rules('email', 'Email', 'required');
if ($this->form_validation->run() == FALSE)
{
$this->load->view('myform');
}
else
{
$this->load->view('formsuccess');
}
}
}
The problem is you are setting $this->data['alert'] values, whether the form is submitting data or not. Of course you could prevent this variable assignment by adding conditional so it will set only when there are any $_POST data is submitted :
// load up the validation rules for blog Info form
$this->config->load('mh_blog_validate');
$this->form_validation->set_rules($this->config->item('validate_blog_update'));
if ($this->form_validation->run('validate_blog_update') === FALSE) {
if ($_POST)
{
$errors = array('message' => $this->upload->display_errors());
$message = array('message' => 'Warning - '.$errors['message'],
'class' => 'danger',
);
$this->data['alert'] = bootstrap_alert($message);
}
}

Codeigniter form_validation->run() is returning false

I know this question has been asked here a ton of times and I have seen the answers, but none of them solves my problem.
I have two REST API's Controllers and in both of them, the form_validation always returns false. When I comment out the validation section, both my controllers work fine.
This is my code.
The first controller is used for registration.
class ApiController extends REST_Controller{
public function create_password($password){
return hash("sha256", $password);
}
public function data_post(){
$this->form_validation->set_rules(
'username','User Name','trim|required|min_length[5]|max_length[30]|is_unique[users.user_name]|xss_clean');
$this->form_validation->set_rules('firstname','First Name','trim|required|alpha|min_lenght[3]|max_length[30]|xss_clean');
$this->form_validation->set_rules('lastname','Last Name','trim|required|alpha|min_lenght[3]|max_length[30]|xss_clean');
$this->form_validation->set_rules('email','Email','trim|required|valid_email|is_unique[users.user_email]');
$this->form_validation->set_rules('password','Password','trim|required');
$this->form_validation->set_rules('cpassword','Confirm Password','trim|required|matches[password]');
$this->form_validation->set_rules('gender','Gender','required');
$this->form_validation->set_rules('dob','Date of Birth','required');
$this->form_validation->set_rules('phone','Mobile Number','required');
if($this->form_validation->run() === FALSE){
$errors = validation_errors();
$message = array(
'status' => FALSE,
'message' => $errors
);
//$this->response($message, REST_Controller::HTTP_NOT_ACCEPTABLE);
echo validation_errors();
return;
}
$userpass = $this->create_password($this->post('password'));
$data = array('user_name'=>$this->post('username'),
'first_name'=>$this->post('firstname'),
'last_name'=>$this->post('lastname'),
'user_email'=>$this->post('email'),
'password'=>$userpass,
'date_of_birth'=> $this->post('dob'),
'mobile_phone' => $this->post('phone'),
'user_gender' => $this->post('gender')
);
$recordEntered = $this->mainModel->insert($data);
$message = '';
if($recordEntered == 1){
$message = array(
'status' => TRUE,
'message' => 'Data Inserted Successfully'
);
}
$this->response($message, REST_Controller::HTTP_CREATED);
}
And this is the 2nd Controller, used for login
class Authentication extends REST_Controller{
function index_post(){
$this->form_validation->set_rules('username','User Name','trim|required|max_length[30]|xss_clean');
$this->form_validation->set_rules('password','Password','trim|required');
if($this->form_validation->run() === false){
$errors = validation_errors();
$message = array(
'status' => FALSE,
'message' => $errors
);
$this->response($message, REST_Controller::HTTP_NOT_ACCEPTABLE);
return;
}
$username = $this->post('username');
$password = $this->create_password($this->post('password'));
$message = '';
if($this->verify_user($username, $password)){
$data = array(
'email' => $this->post('username'),
'is_logged_in' => 1
);
$this->session->set_userdata($data);
$message = array(
'status' => TRUE,
'message' => 'Log In Successful'
);
$this->response($message, REST_Controller::HTTP_OK);
}
else{
$message = array(
'status' => FALSE,
'message' => 'Invalid Email/Username or Password'
);
$this->response($message, REST_Controller::HTTP_NOT_FOUND);
}
}
public function verify_user($username, $password){
if($this->mainModel->getUser($username, $password)){
return true;
}
else{
return false;
}
}
public function create_password($password){
return hash("sha256", $password);
}
}
I am relatively new to Codeigniter and I am under a deadline which expires today.
Any help would be greatly appreciated.
First Change :
Sometimes you may want to validate an array that does not originate from $_POST data.
In this case, you can specify the array to be validated:
$data = array(
'username' => 'johndoe',
'password' => 'mypassword',
'passconf' => 'mypassword'
);
$this->form_validation->set_data($data);
Creating validation rules, running the validation, and retrieving error messages works the same whether you are validating $_POST data or another array of your choice.
You have to call the set_data() method before defining any validation rules.
see this link :
https://www.codeigniter.com/user_guide/libraries/form_validation.html#validating-an-array-other-than-post
Second Change :
In ApiController controller
Please remove xss_clean from the set_rules. xss_clean is not a native rule
$this->form_validation->set_rules('username','User Name','trim|required|min_length[5]|max_length[30]|is_unique[users.user_name]');
$this->form_validation->set_rules('firstname','First Name','trim|required|alpha|min_lenght[3]|max_length[30]');
$this->form_validation->set_rules('lastname','Last Name','trim|required|alpha|min_lenght[3]|max_length[30]');
AND Also from
In Authentication controller
$this->form_validation->set_rules('username','User Name','trim|required|max_length[30]');
Please read this for the reference :
https://www.codeigniter.com/user_guide/libraries/form_validation.html#rule-reference
For security helper ( xss_clean )
https://www.codeigniter.com/user_guide/helpers/security_helper.html
removing the xss_clean makes my code works perfectly

How to check column record present or not if not display error message else insert into database using codeigniter?

I want to check if record is exist then fire error message else insert into database using codeigniter
model.php
public function insert_profile($data){
$this->db->insert('profile', $data);
}
controller.php
public function empprofile(){
$this->form_validation->set_rules('txtname', 'Name', 'trim|required|min_length[6]',
array(
'required' => 'enter your name'));
$this->form_validation->set_rules('txtemail', 'Email', 'trim|required|valid_email',
array(
'required' => 'enter email'));
$this->form_validation->set_rules('txtvpno', 'Vastipatrak No', 'trim|required|min_length[11]',
array(
'required' => 'select Vastipatrak No'));
$this->form_validation->set_rules('txtfield', 'Field', 'trim|required',
array(
'required' => 'enter Field'));
$this->form_validation->set_rules('txtcontact', 'Phone No', 'trim|required|min_length[10]|max_length[10]',
array(
'required' => 'select Phone No'));
$this->form_validation->set_rules('txtexp', 'Experience', 'trim|required',
array(
'required' => 'enter Experience'));
$this->form_validation->set_rules('txtage', 'Age', 'trim|required',
array(
'required' => 'enter age'));
if($this->form_validation->run() ==FALSE){
$this->load->view('submitprofile');
}
else{
$data = array(
'Name' => $this->input->post('txtname'),
'Email' => $this->input->post('txtemail'),
'VPNo' => $this->input->post('txtvpno'),
'Field' => $this->input->post('txtfield'),
'Phone' => $this->input->post('txtcontact'),
'Exp' => $this->input->post('txtexp'),
'Age' => $this->input->post('txtage')
);
$result= $this->mymodel->insert_profile($data);
if ($result == FALSE) {
echo "Vastipatrak No already exist";
}
elseif ($result == 0) {
echo "Something Went Wrong";
}
else{
echo "You have successfully registred with KDOJobs";
}
redirect(site_url('talents'));
}
}
What i can do to check if record is exists or not if yes then display error
In Model
public function insert_profile($data)
{
$VPNo = $data['VPNo'];
$query = $this-db->query("SELECT * FROM profile WHERE vpno = '$VPNo' ");
$result = $query->result_array();
if (count($result) > 0)
{
# data exist
return FALSE;
}
else
{
$this->db->insert('profile', $data);
if ($this->db->affected_rows() > 0)
{
return TRUE;
}
else
{
return 0;
}
}
}
In Controller
$result = $this->mymodel->insert_profile($data);
if ($result == FALSE) {
$this->session->set_flashdata('error', 'Data exist');
}
elseif ($result == 0) {
$this->session->set_flashdata('error', 'Something Went Wrong');
}
else{
$this->session->set_flashdata('success', 'Successfullly Inserted');
}
/*
In your code you using redirect(). So its better to add session like Flash Data.
So once you redirect as soon as function success you can access it in redirected page.
Setting Flash Data
If error
$this->session->set_flashdata('error', 'Data exist');
$this->session->set_flashdata('error', 'Something Went Wrong');
If Success
$this->session->set_flashdata('success', 'Successfullly Inserted');
Accessing Flash data
if(!empty($this->session->flashdata('error'))
{
echo $this->session->flashdata('error');
}
*/
redirect(site_url('talents'));
Links
Flashdata in Codeigniter
There's a better way to use is_unique[table.coloum_name] , I think, still using CodeIgniters' validation library... Use is_unique where you pass an extra parameter which is the id of the row you're editing.. See below.. I use it and works pretty fine for me.. is_unique[table.coloum_name] hope it helps
$this->form_validation->set_rules('txtname', 'Name', 'trim|required|min_length[6]|is_unique[table.coloum_name]', array( 'required' => 'enter your name'));
https://www.codeigniter.com/userguide3/libraries/form_validation.html

Codeigniter reformating POST data after form validation

I have a problem and I can't imagine how this is going on. So I run form_validation to validate my form inputs. After that, $_POST['user_name'] becomes array instead of string.
$this->form_validation->set_rules('user_name', 'Vartotojo vardas',
'trim|required|min_length[5]|max_length[30]|alpha_dash|callback_checkUserNameUnique');
$this->form_validation->set_rules('email', 'El. pašto adresas',
'trim|required|valid_email|callback_checkEmailUnique');
$this->form_validation->set_rules('password', 'Slaptažodis',
'trim|required|min_length[5]|max_length[60]');
$this->form_validation->set_rules('password_2', 'Slaptažodžio pakartojimas',
'trim|required|min_length[5]|max_length[60]|matches[password]');
$this->form_validation->set_rules('phone_number', 'Telefono numeris',
'trim|required|callback_checkIfPhoneGood');
$this->setFormMessages();
if ( $this->form_validation->run() == false ) {
$data['json'] = array(
'failed' => true,
'errors' => $this->form_validation->error_array()
);
} else {
print_r($_POST['user_name']);
print_r($this->input->post('user_name', true));
}
before launching $this->form_validation->run() and printing $_POST['user_name'] it returns string, after $this->form_validation->run() it returns empty array.
Any ideas?
EDIT:
my checkUserNameUnique method:
function checkUserNameUnique($userName)
{
return $this->cache->model('system_model', '_getCustomTableData', array(
'users', array(array('user_name' => strtolower($userName))), 'id DESC', FALSE, 1
), CACHE_USER_CHECK_INFO_TIME);
}
_getCustomTableData returns an array, so change your callback function like this:
function checkUserNameUnique($userName)
{
if (empty($this->cache->model('system_model', '_getCustomTableData', array(
'users', array(array('user_name' => strtolower($userName))), 'id DESC', FALSE, 1
), CACHE_USER_CHECK_INFO_TIME)))
{
return TRUE;
}
else
{
$this->form_validation->set_message('username_unique', 'The %s field must be unique.');
return FALSE;
}
}
Form validation also supports checking uniqueness:
$this->form_validation->set_rules('user_name', 'Vartotojo vardas',
'trim|required|min_length[5]|max_length[30]|alpha_dash|is_unique[users.user_name]');

Form Validation with CodeIgniter + MySql Not Working

I can't seem to get my form validation working with Codeigniter. I've tried extending the Form_validation class by creating My_Form_validation.php and have had no success. I'm now trying the callback method. I was getting errors to show up for a little while, however they were incorrect.
This is the code that is located in my controller:
function create_user() {
$this->load->library('form_validation');
$validate = array(
array(
'field' => 'first_name',
'label' => 'First Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'last_name',
'label' => 'Last Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'trim|required|xss_clean|callback_user_exists'
),
array(
'field' => 'email_address',
'label' => 'Email Address',
'rules' => 'trim|required|valid_email|callback_email_exists'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required|min_length[5]|max_length[32]'
),
array(
'field' => 'password2',
'label' => 'Confirm Password',
'rules' => 'trim|required|matches[password]'
)
);
$this->form_validation->set_rules($validate);
if($this->form_validation->run() == FALSE) {
$this->load->view('user/user-signup');
} else {
$this->load->model('user_model');
if($query = $this->user_model->create_user()) {
$this->load->view('user/user-login');
} else {
$this->index();
}
}
}
function user_exists($username) {
$this->load->model('user_model');
$this->user_model->user_exists($username);
$this->form_validation->set_message('user_exists', 'This username is already taken');
}
function email_exists($email) {
$this->load->model('user_model');
$this->user_model->email_exists($email);
$this->form_validation->set_message('email_exists', 'This email is already in use');
}
And this is the code located in my Model:
function create_user() {
$insert_user = array(
'first_name' => $this->input->post('first_name'),
'last_name' => $this->input->post('last_name'),
'username' => $this->input->post('username'),
'email_address' => $this->input->post('email_address'),
'password' => md5($this->input->post('password'))
);
$insert = $this->db->insert('users', $insert_user);
return $insert;
}
function user_exists($username) {
$this->db->where('username', $username);
$query = $this->db->get('users');
if($query->num_rows > 0) {
return true;
} else {
return false;
}
}
function email_exists($email) {
$this->db->where('email_address', $email);
$query = $this->db->get('users');
if($query->num_rows > 0) {
return true;
} else {
return false;
}
}
I'm wanting to validate by checking to see if a Username or Email Address already exists in the database, and if so, the user will need to make the appropriate changes.
Any ideas?
Your code is very hard to read, so I'll show you how improve it. :)
In your controller, you can use constructor for model loading instead this two lines:
$this->load->model('user_model');
Like this:
function __constructor() {
parent::__constructor();
$this->load->model('user_model');
}
Change your user_exists callback to this:
function user_exists($username) {
$user_check = $this->user_model->user_exists($username);
if($user_check > 0) {
$this->form_validation->set_message('user_exists', 'This username is already taken');
return FALSE;
}
else {
return TRUE;
}
}
Change your email_exists callback to this:
function email_exists($email) {
$check_email = $this->user_model->email_exists($email);
if($check_email > 0) {
$this->form_validation->set_message('email_exists', 'This email is already in use');
return FALSE;
}
else {
return TRUE;
}
}
Now, go back to your model and change these two models methods:
function user_exists($username) {
$this->db->where('username', $username);
$query = $this->db->get('users');
return $query->num_rows();
}
function email_exists($email) {
$this->db->where('email_address', $email);
$query = $this->db->get('users');
return $query->num_rows();
}
Now, you do it wrong because you don't understand what model means. in the models methods, you can write database queries... So, if you want to create an user, you should get inputs' information in the controller and then pass them to the model method create_user, like this:
Controller method create_user:
function create_user() {
$this->load->library('form_validation');
$validate = array(
array(
'field' => 'first_name',
'label' => 'First Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'last_name',
'label' => 'Last Name',
'rules' => 'trim|required|xss_clean'
),
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'trim|required|xss_clean|callback_user_exists'
),
array(
'field' => 'email_address',
'label' => 'Email Address',
'rules' => 'trim|required|valid_email|callback_email_exists'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required|min_length[5]|max_length[32]'
),
array(
'field' => 'password2',
'label' => 'Confirm Password',
'rules' => 'trim|required|matches[password]'
)
);
$this->form_validation->set_rules($validate);
if($this->form_validation->run() == FALSE) {
$this->load->view('user/user-signup');
} else {
$user_data['first_name'] = $this->input->post("first_name");
$user_data['last_name'] = $this->input->post("last_name");
$user_data['username'] = $this->input->post("username");
$user_data['email_address'] = $this->input->post("email_address");
$user_data['password'] = $this->input->post("password");
if($query = $this->user_model->create_user($user_data)) {
$this->load->view('user/user-login');
} else {
$this->index();
}
}
}
Model's method create_user:
function create_user($user_data) {
return $this->db->insert("users", $user_data);
}
That's all, it will work. Good luck.
Have you tried is_unique[table_name.field_name] rule?
Example:
$this->form_validation->set_rules('username', 'Username',
'required|min_length[5]|max_length[12]|is_unique[users.username]');
$this->form_validation->set_rules('email', 'Email',
'required|valid_email|is_unique[users.email]');
Update
If you want to use a callback function then user_exists function should be in the controller instead in the model as you mentioned.
The correct way to define is -
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;
}
}
Re-write your function like this
function user_exists($username) {
$this->load->model('user_model');
$result = $this->user_model->user_exists($username);
if($result != NULL){
$this->form_validation->set_message('user_exists', 'This username is already taken');
return FALSE;
}else{
return TRUE;
}
}
You are not returning true or false therefore it is always getting last true returned by xss_clea.
i have had the same problem.
One of the problems with the callback function is that it can only accept one parameter.
there are two states to consider when checking for uniqueness of a record in your form.
1) you are adding a new record
2) you are editing an existing record.
if you are adding a new record the inbuilt is_unique works fine.
if you are editing an existing record is_unique does not work, because it finds the record you are editing and says the form data is not unique.
to get around this problem i have used the session class, set it for case 2 before you run the validation script, so you need to know if you are editing an existing record, or adding a new record. to do this i just add a hidden input to the form when it is edited, eg the records unique id.
presumably you have a unique user id in your users table, eg so set it before the validation is run.
if($this->input->post('user_id')){$this->session->set_userdata('callback_user_id',$this->input->post('user_id'));}
then in your callback, use this sort of algorithm:
case 1) ie $this->session->userdata('callback_user_id') == FALSE
if the user name is unique, validate, and return true.
if the user name is not unique, return false with validation message user has to be unique.
case 2) ie, the callback_user_id is set.
if the user name is unique, validate and return true
if the user name is already set, and that record has the same id as user_id, that means you are updating the same record, and its fine to validate.
otherwise, another record has the username, and it should fail validation.
in the model i just have a method that returns the unique id for a username.
after you run the validation, its probably a good idea to unset the callback_user_id session variable.
i'm sorry i don't have code to paste, but i think this description should help you.
==== edits
nowadays, i think overriding the form validation with a new function is the way to go.
so: have a language pack entry, a form validation line and the override:
This assumes that a field is posted named ID that has the id of the row.
$lang['form_validation_is_unique_not_current'] ='The {field} field must contain a unique value.';
array('field' => 'username', 'label' => 'lang:…username…', 'rules' => 'trim|required|min_length[2]|max_length[40]|is_unique_not_current[users.username]'),
class MY_Form_validation extends CI_Form_validation {
function __construct($rules = array())
{
parent::__construct($rules);
$this->_error_prefix = '<div class="alert alert-danger"><p>';
$this->_error_suffix = '</p></div>';
}
public function is_unique_not_current($str, $field)
{
sscanf($field, '%[^.].%[^.]', $table, $field);
$id = $this->CI->input->post('id');
if($this->CI->input->post('field_name'))
{
return isset($this->CI->db)
? ($this->CI->db->limit(1)->get_where($table, array(
$field => $str,
'id <> ' => $id))->num_rows() === 0)
: FALSE;
}
return FALSE;
}
}

Categories