Codeigniter - re-populating form on failed validation after submitting - php

I have a form that requires the user to enter some information. If they fail to complete the required fields they are re-presented with the form; the top of the page notifying them what fields are required and I've enabled sticky forms (set_value()) so their input is not lost.
I'm using flashdata to display messages to the user (i.e., if what they've entered already exists in the database).
My form is in the index method of my controller.
When submit is clicked from my view it calls the add() method in my controller.
The add() method performs the validation and depending on the results either submits to the database or kicks back out to the user to get more data.
I have several issues with the way that i've done this.
1. If validation fails I'm using $this->index() to get back to my form and display the validation errors. If I try using redirect, I lose my validation errors and my $_POST[] data so my sticky forms end up blank.
2. Using $this->index() appends the 'add' to the end of my url
3. Using $this->index() causes issues with the flashdata. Random results.
Any ideas?
<?php
class Restaurant extends Controller {
function Restaurant() {
parent::Controller();
}
function index() {
// Load libraries and models
$this->load->model('/restaurant/mRestaurantTypes');
$this->load->model('/restaurant/mRestaurant');
$this->load->model('/utilities/mUtilities');
// Get states
$stateSelect = array();
$getStates = $this->mUtilities->getStates();
if($getStates->num_rows() > 0) {
foreach($getStates->result() as $row) {
$stateSelect[$row->abbr] = $row->name;
}
}
// Get restaurant types
$restaurantTypes = array();
$getRestaurantTypes = $this->mRestaurantTypes->getRestaurantTypes();
if($getRestaurantTypes->num_rows() > 0) {
foreach($getRestaurantTypes->result() as $row) {
$restaurantTypes[$row->restaurant_types_id] = $row->type;
}
}
// Create form elements
$data['name'] = array(
'name' => 'name',
'id' => 'name',
'value' => set_value('name'),
'maxlength' => '200',
'size' => '50'
);
$data['address'] = array(
'name' => 'address',
'id' => 'address',
'value' => set_value('address'),
'maxlength' => '200',
'size' => '50'
);
$data['city'] = array(
'name' => 'city',
'id' => 'city',
'value' => set_value('city'),
'maxlength' => '50',
'size' => '25'
);
$data['state'] = $stateSelect;
$data['zip'] = array(
'name' => 'zip',
'id' => 'zip',
'value' => set_value('zip'),
'maxlength' => '10',
'size' => '10'
);
$data['phone'] = array(
'name' => 'phone',
'id' => 'phone',
'value' => set_value('phone'),
'maxlength' => '15',
'size' => '15'
);
$data['url'] = array(
'name' => 'url',
'id' => 'url',
'value' => set_value('url'),
'maxlength' => '255',
'size' => '50'
);
$data['type'] = $restaurantTypes;
$data['tags'] = array(
'name' => 'tags',
'id' => 'tags',
'value' => set_value('tags'),
'maxlength' => '255',
'size' => '50'
);
$data['active'] = array(
'name' => 'active',
'id' => 'active',
'value' => 'Y',
'maxlength' => '1',
'size' => '2'
);
// Set page variables
$data_h['title'] = "Add new restaurant";
// Load views
$this->load->view('/template/header', $data_h);
$this->load->view('/restaurant/index', $data);
$this->load->view('/template/footer');
}
/**
* Add the the new restaurant to the database.
*/
function add() {
// Load libraries and models
$this->load->library('form_validation');
$this->load->model('/restaurant/mRestaurant');
// Define validation rules
$this->form_validation->set_rules('name', 'Name', 'trim|required|max_length[255]|xss_clean');
$this->form_validation->set_rules('address', 'Address', 'trim|required|max_length[100]|xss_clean');
$this->form_validation->set_rules('city', 'City', 'trim|required|max_length[128]|xss_clean');
//$this->form_validation->set_rules('state', 'State', 'trim|required');
$this->form_validation->set_rules('zip', 'Zip', 'trim|required|max_length[128]|xss_clean');
$this->form_validation->set_rules('phone', 'Phone', 'trim|required|max_length[10]|xss_clean');
$this->form_validation->set_rules('url', 'URL', 'trim|required|max_length[255]|xss_clean');
$this->form_validation->set_rules('tags', 'Tags', 'trim|xss_clean');
// Form validation
if ($this->form_validation->run() == FALSE) {
// On failure
$this->index();
} else {
// On success, prepare the data
$data = array(
'name' => $_POST['name'],
'address' => $_POST['address'],
'city' => $_POST['city'],
'state' => $_POST['state'],
'zip' => $_POST['zip'],
'phone' => $_POST['phone'],
'url' => $_POST['url'],
'type' => $_POST['type'],
'tags' => $_POST['tags'],
'active' => $_POST['active'],
);
// Check if the restaurant already exists
$check = $this->mRestaurant->getRestaurant($data['name'], $data['zip']);
// If no records were returned add the new restaurant
if($check->num_rows() == 0) {
$query = $this->mRestaurant->addRestaurant($data);
if ($query) {
// On success
$this->session->set_flashdata('status', '<div class="success">Added New Restaurant!</div>');
} else {
// On failure
$this->session->set_flashdata('status', '<div class="error">Could not add a new restaurant.</div>');
}
redirect('restaurant/confirm', 'refresh');
} else {
// Notify the user that the restaurant already exists in the database
$this->session->set_flashdata('status', '<div class="notice">This restaurant already exists in the database.</div>');
redirect('restaurant/index');
}
}
}
function confirm() {
$data['title'] = "Confirm";
$this->load->view('/template/header');
$this->load->view('/restaurant/confirm', $data);
$this->load->view('/template/footer');
}
}
?>

I will try to help with the logic in the controller that I always use:
function index()
{
//set some default variables
$data['error_message'] = '';
//if this is to edit existing value, load it here
// from database and assign to $data
//...
//set form validation rules
$validation = array();
$validation['field_name'] = array(
'field' => 'field_name',
'label' => 'Field label',
'rules' => 'trim|required'
);
//more rules here
//...
$this->load->library('form_validation');
$this->form_validation->set_rules($validation);
//run validation
if ($this->form_validation->run() == FALSE)
{
$data['error_message'] .= validation_errors();
}
else
{
//do insert/update
//
//it's better to do redirection after receiving post request
//you can use flashdata for success message
if ( $success )
{
$this->session_set_flashdata('success_message', MESSAGE_HERE);
}
redirect(RESULT_PAGE);
}
//reaching this block can have 2 meaning, direct page access, or not have valid form validation
//assign required variables, such as form dropdown option, etc
//...
//load view
$this->load->view(VIEW_FILE, $data);
}
View file:
...
<?php if ( $error_message ): ?>
<?php echo $error_message; ?>
<?php endif; ?>
<?php echo form_open(current_url, array('id' => 'some_form_id')); ?>
<!-- form field here -->
<label for="field_name">Field label</label>
<input name="field_name" value="<?php echo set_value('field_name', $DEFAULT_FIELD_NAME_IF_NEEDED); ?>" />
<!-- more form field here -->
<?php echo form_close(); ?>
...
I hope this will help you.
For the $DEFAULT_FIELD_NAME_IF_NEEDED in the view file, I use this to pass the default value if this form page is to edit existing data from database. You can load the data in the controller, then pass it to view file and display it in the form field.

-------controller-------
$data['post'] = $_POST;
$this->load->view('view/view', $data);
then in your view
<input type="text" value="><?=$post['username'];?>" name="username">

I had a similar problem and I ended up doing:
My form is to create new user but you should get the idea.
if($this->form_validation->run() == FALSE)
{
$this->data['title'] = "Add User";
$this->load->vars($this->data);
$this->load->view('head');
$this->load->view('header');
$this->load->view('admin/sidebar');
$this->load->view('admin/add_user');
$this->load->view('footer');
}
So effectively instead of calling new function I was showing new view from the same function.
Not the nicest solution but it works.
Also you might want to use something like this to check if the restaurant already exists:
function _check_username($str)
{
$this->db->where('username', $str);
$query = $this->db->get('sm_users');
if($query->num_rows() == 0)
{
return TRUE;
}
else
{
$this->form_validation->set_message('_check_username', "User '$str' already exists!");
return FALSE;
}
}
And use callback validation function:
$this->form_validation->set_rules('userName','User Name','trim|required|min_length[3]|callback__check_username');

You could try having the form post to index, and in the index method, do validation if the form has been submitted. Then either render the index view (if there are errors) or add the restaurant and render the confirm view.

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 - update single record by ID - failing

Am a new user to CodeIgniter, have looked at other posts and the answers given sadly don't solve this issue.
Am using a form to create records (also uploads image file and creates link to image as field in db) This all works. I am now trying to edit a particular record. I have a view with the form and this works and is pre-filled from the db using $id = $this->uri->segment(3) to grab the correct record - this all works.
Where it fails is then in updating the record.
My controller...
function edit_stock_vehicle_record()
{
$this->load->library('form_validation');
// field name, error message, validation rules
$this->form_validation->set_rules('title', 'Title', 'trim|required');
$this->form_validation->set_rules('make', 'Make', 'trim|required');
$this->form_validation->set_rules('model', 'Model', 'trim|required');
$this->form_validation->set_rules('fuel', 'Fuel Type', 'trim|required');
$this->form_validation->set_rules('enginesize', 'Engine Size', 'trim|required');
$this->form_validation->set_rules('trans', 'Transmission', 'trim|required');
$this->form_validation->set_rules('reg_no', 'Registration Number', 'trim|required');
$this->form_validation->set_rules('year', 'Year', 'trim|required');
$this->form_validation->set_rules('colour', 'Colour', 'trim|required');
$this->form_validation->set_rules('mileage', 'Mileage', 'trim|required');
$this->form_validation->set_rules('long_desc', 'Description', 'trim|required');
$this->form_validation->set_rules('purchase_price', 'Purchase Price', 'trim|required');
$this->form_validation->set_rules('sale_price', 'Sale Price', 'trim|required');
if($this->form_validation->run() == FALSE)
{
$data['main_content'] = 'vehicle_display2';
$this->load->view('includes/template', $data);
}
else
{
$this->load->model('manage_model');
if($query = $this->manage_model->edit_stock_vehicle_record())
{
$data['main_content'] = 'vehicle_added';
$this->load->view('includes/template', $data);
}
else
{
$data['main_content'] = 'add_vehicle4';
$this->load->view('includes/template', $data);
}
}
}
My model....
function edit_stock_vehicle_record()
{
$this->load->helper('array');
$this->load->helper('html');
$id = $this->uri->segment(3);
$config['upload_path'] = 'c:/wamp/www/honest/images';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '5000';
$config['overwrite'] = TRUE;
$config['remove_spaces'] = TRUE;
$this->load->library('upload', $config);
if ( ! $this->upload->do_upload())
{
$error = array('error' => $this->upload->display_errors());
$data['main_content'] = 'imageupload';
$this->load->view('includes/template', $data);
echo "FAILED";
}
else
{
$image_data = $this->upload->data();
$vehicle_update_data = array(
'title' => $this->input->post('title'),
'make' => $this->input->post('make'),
'model' => $this->input->post('model'),
'fuel' => $this->input->post('fuel'),
'enginesize' => $this->input->post('enginesize'),
'trans' => $this->input->post('trans'),
'reg_no' => $this->input->post('reg_no'),
'year' => $this->input->post('year'),
'colour' => $this->input->post('colour'),
'mileage' => $this->input->post('mileage'),
'long_desc' => $this->input->post('long_desc'),
'purchase_price' => $this->input->post('purchase_price'),
'sale_price' => $this->input->post('sale_price'),
'image' => $image_data['file_name']
);
$this->load->helper('url');
$id = $this->uri->segment(3);
$update = $this->db->update('stock_vehicles', $vehicle_update_data, array('id' => $id));
return $update;
}
}
I have also tried versions using....
$this->db->where('id', $id);
$this->db->update('stock_vehicles', $vehicle_update_data);
But this also fails, it seems as if the $id is not being recognized correctly.
If I remove the above and just use $this->db->update('stock_vehicles', $vehicle_update_data); it does indeed update every record in the db (doh!) Fortunately there was no 'real' data in there when I discovered this!
Not sure why it is not picking up the $id - all input gratefully received.
Cheers,
DP.
I have a view with the form and this works and is pre-filled from the
db using $id = $this->uri->segment(3) to grab the correct record -
this all works.
Do NOT do this for the form update. Just include the id in a hidden form field. Much easier, safer, etc.
echo form_hidden( 'id', $id );
first you must load the url helper in your Controller:
$this->load->helper('url');
then you should try this code:
$id = $this->uri->segment(3);
$vehicle_update_data =array(
'title' => $this->input->post('title'),
'make' => $this->input->post('make'),
'model' => $this->input->post('model'),
'fuel' => $this->input->post('fuel'),
'enginesize' => $this->input->post('enginesize'),
'trans' => $this->input->post('trans'),
'reg_no' => $this->input->post('reg_no'),
'year' => $this->input->post('year'),
'colour' => $this->input->post('colour'),
'mileage' => $this->input->post('mileage'),
'long_desc' => $this->input->post('long_desc'),
'purchase_price' => $this->input->post('purchase_price'),
'sale_price' => $this->input->post('sale_price'),
'image' => $image_data['file_name']
);
$this->db->WHERE('id',$id)->update('your_table',$vehicle_update_data);
return true;

zf2 - need help on multi page form in one page

I'm just learning zf2, and the basic tutorial from official document is great. Now, I would like to challenge myself to create multi page form in one page, something like that http://demo.stepblogging.com/multi-step-form/
So, currently I have two forms called "Contact Form" and "Album Form".
The idea is i want to split to 2 forms. The problem is when i finish all the fields on the first form, i'm not sure how to go to next form. I'm not sure i can do the logic at Controller, what i know most of the online tutorials are using javascript to handle the next and back button. Or maybe have better idea?
So this is my Controller page.
public function multipleAction(){
$formOne = new ContactForm();
$formTwo = new AlbumForm();
$formOne->get('next')->setValue('Next');
$request = $this->getRequest();
if($request->isPost()){
$aa = new ContactFilter();
$formOne->setInputFilter($aa);
$formOne->setData($request->getPost());
if ($formOne->isValid()) {
//save session
//maybe display second form or any other solution
}
}
my multiple.phtml page contains 2 forms
<ul id="signup-step">
<li id="contact" class="active">Contact</li>
<li id="album">Album</li>
</ul>
<?php
$form_one = $this->form_one;
//$form_one->setAttribute('action', $this->url('album', array('action' => 'multiple')));
$form_one->prepare();
//echo $_SESSION['name'];
echo $this->form()->openTag($form_one); ?>
<div id="contact-field">
<legend>Contact</legend>
<?php
echo $this->formHidden($form_one->get('id'));
echo $this->formLabel($form_one->get('name')).'<br>';
echo $this->formInput($form_one->get('name'))."<br>";
echo $this->formElementErrors($form_one->get('name'));
echo $this->formLabel($form_one->get('artist')).'<br>';
echo $this->formInput($form_one->get('artist'))."<br>";
echo $this->formElementErrors($form_one->get('artist'));
echo $this->formLabel($form_one->get('address')).'<br>';
echo $this->formInput($form_one->get('address'))."<br><br>";
echo $this->formElementErrors($form_one->get('address'));
echo $this->formSubmit($form_one->get('next'));
echo $this->form()->closeTag($form_one);
?>
<?php
$form_two = $this->form_two;
$form_two->prepare();
echo $this->form()->openTag($form_two); ?>
<div id="album-field" >
<legend>Album</legend>
<?php
echo $this->formLabel($form_two->get('title')).'<br>';
echo $this->formInput($form_two->get('title'))."<br>";
echo $this->formElementErrors($form_two->get('title'));
echo $this->formLabel($form_two->get('artist'))."<br>";
echo $this->formInput($form_two->get('artist'))."<br>";
echo $this->formElementErrors($form_two->get('artist'));
echo $this->form()->closeTag($form_two);
?>
The code below is very crude and is only for example purposes (made this in 10 mins and looks like it)
So basically all we are doing is the following -
Creating a session
Checking if there is any data in the session for that particular form, if there is one then use setData() to set the data on the form
If the form posts data, then validate & filter it and then save that data to the session
The "Submit" button value in the form is used to determine the navigation path i.e. previous or next page.
The final page will save data from the session to the DB (or whatever you want to do with it) and of course destroy the session as well.
Controller
/** #var Zend\Session\Container Session Object */
private $session;
public function __construct()
{
// Put a meaningful name in the constructor
$this->session = new Container();
}
public function page1Action()
{
// This should really be injected...
$form = new Form\Form1();
// Proper validation & filtering needs to be done for every form (this is example only)
$form->setInputFilter(new InputFilter());
// Populates form data from the session if it already exists
if (isset($this->session->form1Inputs)) {
$form->setData($this->session->form1Inputs);
}
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$formData = $form->getData();
// Saves the new data to the session
$this->session->form1Inputs = $formData;
// Redirects to next page
if ($formData['Next'] === 'Next') {
$this->redirect()->toRoute('application', ['controller' => 'Index', 'action' => 'page2']);
}
}
}
return new ViewModel(['form' => $form]);
}
public function page2Action()
{
// This should really be injected...
$form = new Form\Form2();
// Proper validation & filtering needs to be done for every form (this is example only)
$form->setInputFilter(new InputFilter());
// Populates form data from the session if it already exists
if (isset($this->session->form2Inputs)) {
$form->setData($this->session->form2Inputs);
}
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$formData = $form->getData();
// Saves the new data to the session
$this->session->form2Inputs = $formData;
// Redirects to next or previous page
if ($formData['Next'] === 'Next') {
$this->redirect()->toRoute('application', ['controller' => 'Index', 'action' => 'page3']);
} elseif ($formData['Previous'] === 'Previous') {
$this->redirect()->toRoute('application', ['controller' => 'Index', 'action' => 'page1']);
}
}
}
return new ViewModel(['form' => $form]);
}
public function page3Action()
{
// This should really be injected...
$form = new Form\Form3();
// Proper validation & filtering needs to be done for every form (this is example only)
$form->setInputFilter(new InputFilter());
// Populates form data from the session if it already exists
if (isset($this->session->form2Inputs)) {
$form->setData($this->session->form2Inputs);
}
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$formData = $form->getData();
// Saves the new data to the session
$this->session->form3Inputs = $formData;
// Finalise or redirect to previous page
if ($formData['Finalise'] === 'Finalise') {
// Save all data to DB from session & destroy
} elseif ($formData['Previous'] === 'Previous') {
$this->redirect()->toRoute('application', ['controller' => 'Index', 'action' => 'page2']);
}
}
}
return new ViewModel(['form' => $form]);
}
Form 1
public function __construct($name = null)
{
parent::__construct($name);
$this->add(['name' => 'Form1Text1', 'type' => 'Text', 'options' => ['label' => 'Form 1 Text 1 : ']]);
$this->add(['name' => 'Form1Text2', 'type' => 'Text', 'options' => ['label' => 'Form 1 Text 2 : ']]);
$this->add(['name' => 'Next', 'type' => 'Submit', 'attributes' => ['value' => 'Next']]);
}
Form 2
public function __construct($name = null)
{
parent::__construct($name);
$this->add(['name' => 'Form2Text1', 'type' => 'Text', 'options' => ['label' => 'Form 2 Text 1 : ']]);
$this->add(['name' => 'Form2Text2', 'type' => 'Text', 'options' => ['label' => 'Form 2 Text 2 : ']]);
$this->add(['name' => 'Next', 'type' => 'Submit', 'attributes' => ['value' => 'Next']]);
$this->add(['name' => 'Previous', 'type' => 'Submit', 'attributes' => ['value' => 'Previous']]);
}
Form 3
public function __construct($name = null)
{
parent::__construct($name);
$this->add(['name' => 'Form3Text1', 'type' => 'Text', 'options' => ['label' => 'Form 3 Text 1 : ']]);
$this->add(['name' => 'Form3Text2', 'type' => 'Text', 'options' => ['label' => 'Form 3 Text 2 : ']]);
$this->add(['name' => 'Previous', 'type' => 'Submit', 'attributes' => ['value' => 'Previous']]);
$this->add(['name' => 'Finalise', 'type' => 'Submit', 'attributes' => ['value' => 'Finalise']]);
}
i don't think i have understand exactly what you want,
but if you mean multiple steps with different form, so you have just to put the
previous step result in session,
your question is fuzzy. your given link is also done by jquery!... As far as I understand you want this demo page behavior without using js/jquery.
1. break this one form into three form. For easiness add a hidden field step
2. make next and back button input type submit
3. after submit in your action check submitted value and determine what you want ...[show next form or whatever]

CodeIgniter form_validation->run() always returns false?

I'm new to CodeIgniter and I've been trying to implement a form submitting function, however whenever I press "submit" the form page simply refreshes and the database is not updated! It seems that the $this->form_validation->run() is always returning false, but I have no idea why.
The controller function is as follows:
public function write_prof_review($prof_id)
{
$this->load->model('Queries');
// form stuff here
$this->load->helper('form');
$this->load->library('form_validation');
$data['prof_id'] = $prof_id;
if($this->form_validation->run() == FALSE){
$this->load->view('create_prof_review', $data);
}
else {
$this->Queries->submit_prof_review($prof_id, $this->USERID);
$this->load->view('form_submitted');
}
}
And here is the function submit_prof_review() in the model:
function submit_prof_review($prof_id, $user_id)
{
$data = array(
'course_code' => $this->input->post('course_code'),
'easiness' => $this->input->post('easiness'),
'helpfulness' => $this->input->post('helpfulness'),
'clarity' => $this->input->post('clarity'),
'comment' => $this->input->post('comment')
);
$average = round((($data['easiness'] + $data['helpfulness'] + $data['clarity'])/3),2);
date_default_timezone_set('Asia/Hong_Kong');
$date = date('m/d/Y h:i:s a', time());
$data['average'] = $average;
$data['date'] = $date;
$data['course_id'] = 0;
return $this->db->insert('review_prof', $data);
}
And finally the view for the form (create_prof_review.php):
<h2>Write a review</h2>
<?php echo form_open('home/write_prof_review/'.$prof_id); ?>
<h3>Course code
<input type = 'text' name = 'course_code'></h3>
<h3>Easiness
<input type = 'text' name = 'easiness'></h3>
<h3>Helpfulness
<input type = 'text' name = 'helpfulness'></h3>
<h3>Clarity
<input type = 'text' name = 'clarity'></h3>
<h3>Comment</h3>
<textarea name = 'comment' rows = '4' cols = '50'></textarea>
<br>
<input type = 'submit' name = 'submit' value = 'Submit'>
</form>
Been stuck on this for a couple of days, but I still can't figure out what's wrong. Any help would be greatly appreciated!
I think this is happening because you have not set any validation rules.
Controller code should look like this:
public function write_prof_review($prof_id)
{
$this->load->model('Queries');
// form stuff here
$this->load->helper('form');
$this->load->library('form_validation');
$data['prof_id'] = $prof_id;
// here it is; I am binding rules
$this->form_validation->set_rules('course_code', 'Course Code', 'required');
$this->form_validation->set_rules('easiness', 'easiness', 'required');
$this->form_validation->set_rules('helpfulness', 'helpfulness', 'required');
if($this->form_validation->run() == FALSE) {
$this->load->view('create_prof_review', $data);
}
else {
$this->Queries->submit_prof_review($prof_id, $this->USERID);
$this->load->view('form_submitted');
}
}
Please refer to the CodeIgniter user guide; it will give you more information about validation rules.
I had the same problem though the cause was different. I was missing one of the input fields that I was validating from the form i.e
private function validate_data(){
$validate_data = array(
array(
'field' => 'steps',
'label' => 'Steps',
'rules' => 'trim|required|integer|xss_clean'
),
array(
'field' => 'pace',
'label' => 'Pace',
'rules' => 'trim|required|integer|xss_clean'
),
array(
'field' => 'speed',
'label' => 'Speed',
'rules' => 'trim|required|numeric|xss_clean'
),
array(
'field' => 'distance',
'label' => 'Distance',
'rules' => 'trim|required|numeric|xss_clean'
)
);//end array validate_data
return $validate_data;
}
I was missing the speed input field in the form. I added it and the problem was solved. It really gave me a headache cause I was just reusing code that I have used so many times, so I could not understand why ($this->form_validation->run() was returning false, something that I had never experienced before.
You can go to system/library/Form_validation.php
and in
if (count($this->_config_rules) == 0)
{
return FALSE;
}
change false to true

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