Welcome Guest, Not a member yet? Register   Sign In
Reinserting on refresh
#1

[eluser]saidbakr[/eluser]
Hello,

I followed the procedures of form validation acooriding to the documentation. However, my application suffer from reinserting data into the databse again with refresh the result page.

The following is general overview of the code that I use:
Code:
<?php

class Admin extends Controller {
    
    function add_user()
    {
        $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');
                    
        if ($this->form_validation->run() == FALSE)
        {
            
                      $this->load->view('myform');
        }
        else
        {
            //[color=blue]Inserting Into the databse code here[/color]
                      $this->load->view('formsuccess');
        }
    }
    
    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;
        }
    }
    
}
?>

I wonder how could I able to eleminate this?!
#2

[eluser]Cro_Crx[/eluser]
You should write a callback function to check and make sure that the username isn't already taken. That way when you refresh the page and resend the post data then it won't create another username. It will simply tell you the username is already taken.

Also that custom callback function you've created "username_check" is publicly accessible which you probably don't want. This means that you could actually access the URL 'admin/username_check' and it would run the function instead of showing a 404. To get around this you can put an underscore prefix on your functions name: 'function _username_check' and then just call it with 'callback__username_check'
#3

[eluser]Craig A Rodway[/eluser]
It is advised that you do a full redirect once you have inserted data into the database to avoid just this issue. I'll not go into too much detail - you can do that at your leisure here: Post/Redirect/Get; but essentially:

Quote:Post/Redirect/Get (PRG) is a common design pattern for web developers to help avoid certain duplicate form submissions and allow user agents to behave more intuitively with bookmarks and the refresh button.

Just replace this:

Code:
$this->load->view('formsuccess');

with this:

Code:
redirect('admin/success');

And make a function called success which has the line from above. Or whatever other suitable page you want to redirect to...
#4

[eluser]Johan André[/eluser]
[quote author="saidbakr" date="1262482300"]Hello,

I followed the procedures of form validation acooriding to the documentation. However, my application suffer from reinserting data into the databse again with refresh the result page.

The following is general overview of the code that I use:
Code:
<?php

class Admin extends Controller {
    
    function add_user()
    {
        $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');
                    
        if ($this->form_validation->run() == FALSE)
        {
            
                      $this->load->view('myform');
        }
        else
        {
            //[color=blue]Inserting Into the databse code here[/color]
                      $this->load->view('formsuccess');
        }
    }
    
    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;
        }
    }
    
}
?>

I wonder how could I able to eleminate this?![/quote]

Try this out. Good for the app security too:

Use as a library...

Code:
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Formkey
{
    private $formkey;
    private $old_formkey;
    
    function __construct()
    {
        $this->ci = & get_instance();
        $this->ci->load->library('session');
        $this->ci->load->library('form_validation');
            
        if($this->ci->session->userdata('formkey'))
        {
            $this->old_formkey = $this->ci->session->userdata('formkey');
        }
    }

    private function generate_key()
    {
        $ip = $this->ci->input->ip_address();
        $uniqid = uniqid(mt_rand(), true);
        return md5($ip . $uniqid);
    }

    
    public function render_field()
    {
        $this->formkey = $this->generate_key();
        $this->ci->session->set_userdata('formkey', $this->formkey);
        return form_hidden('formkey', $this->formkey);
    }

    public function validate()
    {
        if($this->ci->input->post('formkey') == $this->old_formkey)
        {
            return TRUE;
        }
        else
        {
            $this->ci->form_validation->set_message('_check_formkey', '%s is wrong!');
            return FALSE;
        }
    }
    
}

/* End of file */
#5

[eluser]saidbakr[/eluser]
[quote author="Craig A Rodway" date="1262485488"]It is advised that you do a full redirect once you have inserted data into the database to avoid just this issue. I'll not go into too much detail - you can do that at your leisure here: Post/Redirect/Get; but essentially:

Quote:Post/Redirect/Get (PRG) is a common design pattern for web developers to help avoid certain duplicate form submissions and allow user agents to behave more intuitively with bookmarks and the refresh button.

Just replace this:

Code:
$this->load->view('formsuccess');

with this:

Code:
redirect('admin/success');

And make a function called success which has the line from above. Or whatever other suitable page you want to redirect to...[/quote]
Thank you all, The solution of PRG is suitable for me and it is worked fine.
#6

[eluser]saidbakr[/eluser]
[quote author="Craig A Rodway" date="1262485488"]...
Code:
redirect('admin/success');

And make a function called success which has the line from above. Or whatever other suitable page you want to redirect to...
[/quote]
Another little question:
I don't like to make the redirection to another controller's function. In other word, I'd like to make it to admin/ and attaching a query string to it, so that it should be something like
admin/?msg=insert_ok or admin/insert_ok

Inorder to check this string in the controller's function of admin then doing some other stuff.

However, this approach leads to 404 error. Is there a soultion other than making new controller's function named insert_ok?

I know it's possible to make something like:
Code:
function insert_ok()
{
$this->index();
}

But in this case, is there a way to change uri from admin/insert_ok.html to admin/ ?
#7

[eluser]Craig A Rodway[/eluser]
I would use the Session's flashdata facility to store a message like that. E.g:

Code:
$this->session->set_flashdata('success', 'Record inserted successfully');

You can read this with:

Code:
$this->session->flashdata('success');

Flashdata lasts for a single HTTP request only, and is discarded after that. More info on the session user guide page.
#8

[eluser]saidbakr[/eluser]
[quote author="Craig A Rodway" date="1262829438"]I would use the Session's flashdata facility to store a message like that. E.g:

Code:
$this->session->set_flashdata('success', 'Record inserted successfully');

You can read this with:

Code:
$this->session->flashdata('success');

Flashdata lasts for a single HTTP request only, and is discarded after that. More info on the session user guide page.[/quote]
Yes! It is wonderful solution.

Also I may suggest to pass an optional parameter to the index() function of the controller. i.e.
Code:
function index($msg='')
{
//index code
}
However, the solution of flashdata still the best due to the change of the url rather than admin/.




Theme © iAndrew 2016 - Forum software by © MyBB