views:

1787

answers:

4

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');
    }
}
?>
A: 

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.

Coomer
I moved all of the code from the add() method to index(), I then tried validating if the from has been submitted:if(isset($_POST['add'])) { ~~ }This works the first time that the form is rendered; however, because $_POST['add'] is set, the next time the user hits add and the validation rules still haven't been meet it'll loop.I would still like to use the add() method instead of lumping all the code in index.
mazer
I think you want it to loop until the validation rules all pass, right?And you could move all of your validation and adding code to private methods or library methods and then call them from the index method if desired.
Coomer
A: 

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');
LukeP
A: 

-------controller-------

$data['post'] = $_POST;
$this->load->view('view/view', $data);

then in your view

<input type="text" value="><?=$post['username'];?>" name="username">

Tom Schlick
A: 

Hi mazer,

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.

Donny Kurnia