1

I have a problem with updating database using AJAX and CodeIgniter. When someone posts AJAX form I retrieve data about user from database this way:

class MY_Controller extends CI_Controller 
{
    public $memberData;

    public function __construct() 
    {
        parent::__construct();

        $this->memberData= $this->membermodel->getmemberData();
    }
}

(Every controller extend MY_Controller, not CI_Controller).

Then I operate on user data and insert it to database. The problem is that if I send AJAX post really fast (few at same time), few inserted rows are identical (except auto-increment row ID). It looks like CodeIgniter did not receive new user data from database (or don't update it before), and I operate on old one.

I send AJAX like this:

$("#form_id").submit(function(event)
{

    $form = $(this);

    $.post($form.attr('action'), $(this).serialize(), function(HTML)
    {
        //do something

    });
    return false;
});

then I operate on something like this:

$CI =& get_instance();
$CI->load->model('membermodel', 'member');

$variab['value3'] = $CI->memberData->member_value3 + 1; //this is the line that need to be new on every call, but it doesnt

$variab['result'] = $this->calculatedata($variab['value3']);

$parameters = array(
    'member_value3' => $variab['value3']
);

//update that variable to database, so it should have new value new on next call
$CI->member->updateinfo($parameters);

return $variab['value3'];

At the end I get that value3, base on it my whole script and insert last query to database. Unfortunately like I said if I send many POST requests in the same time that value is constant.

halfer
  • 19,824
  • 17
  • 99
  • 186
6DM
  • 21
  • 8
  • What did you expect? you need a new logic, I guess let user know that he can do submits only 1 per 10 seconds... – Kyslik Dec 12 '14 at 07:51
  • I expect helpful comment, that can help me to understand why things like this happend – 6DM Dec 12 '14 at 08:17
  • 1
    Open up chrome developer tools, write in your JavaScript some `console.log()` statements and see yourself. I didn't mean to be rude but this kind of problem is pure logic. The best option is to lock user for 2-5 seconds (disable submit button). Why this is happening is because you load a value_x send value_y and want to receive vaule_z and do this lots of time in a row... value_y is not saved yet therefore you pull (OLD) value_x again... besides fix this code `calculatedata($variab['value3']);` (removed `'`) – Kyslik Dec 12 '14 at 08:26
  • Can I efficiency limit this server-side, or wait until update is done? Where I can I dont want to trust user. – 6DM Dec 12 '14 at 08:35
  • You need to validate sent data in order to be safe (duplicates, empty fields, permissions). Use [CodeIgniter's validator](https://ellislab.com/codeigniter/user-guide/libraries/form_validation.html). I gave you client side solution because you did not provide enough PHP code. – Kyslik Dec 13 '14 at 22:11

1 Answers1

3

I use this, it should work out of clipboard, I found it a while ago on SO don't remember the source. (will search for it) source.

Please do read comments and do debug using console.

var r;

$("#form_id").submit(function(event){

    if (r) {
        r.abort(); //abort all previous requests
    }
    var $form = $(this);

    var $inputs = $form.find("input, textarea, select, button"); //serialize all elements in form

    var serializedData = $form.serialize(); //serialize data (prep data)
    $inputs.prop("disabled", true); //disable inputs


    r = $.ajax({
        url: $form.attr('action'), //whatever.php
        type: "post",
        data: serializedData
    });

    // Callback handler that will be called on success
    r.done(function (response, textStatus, jqXHR){
        console.log("Form works: " + response);
    });

    // Callback handler that will be called on failure
    r.fail(function (jqXHR, textStatus, errorThrown){
        console.error(
            "Error: "+
            textStatus, errorThrown
        );
    });

    r.always(function () {
        $inputs.prop("disabled", false); //enable inputs
    });

    // Prevent default posting of form
    event.preventDefault();
});

Regard to comment: But if somebody change this JS code he still will be able to bug my whole script, I have to get it secured.

Please consider following order of developing.

  1. create form using HTML
  2. create php file that accepts this form and VALIDATES it; debug all possible inputs etc.
  3. create AJAX part
  4. style using CSS, show errors etc.

This way you will never (rarely) have problems in matter you just did.

Community
  • 1
  • 1
Kyslik
  • 8,217
  • 5
  • 54
  • 87
  • But if somebody change this JS code he still will be able to bug my whole script, I have to get it secured. If I cant fix my code, maybe you can show me way how to plan this properly – 6DM Dec 12 '14 at 09:07
  • 1
    I see what you mean, just do a check in server side (PHP); if both value_3 are the same someone tampered with JavaScript thats it. – Kyslik Dec 12 '14 at 09:11
  • Thanks for advices, but it doesnt work. Even if I get data from database it is before update, so I'm at this same point as before. – 6DM Dec 13 '14 at 21:11