0

I am using jquery sortable and trying to save these items' positions into a mysql table's row named "position". I can't seem to get them to save/update correctly. Everything is working ok on the jquery side, just the php update function. Right now it is saving the position rows as 3, which I get why. I just can't seem to wrap my head around how to do this properly.

Here's what I have for the PHP:

$id = $_POST['id'];
$arr = $_POST['positions'];

foreach($arr as $r) {
   $sql = " UPDATE items
            SET   position = '$r'
            WHERE groupId = '$id' ";
}

Table Structure / desired output:

id | groupId | position
----------------------------
3    10       0
6    8        -
8    10       3
10   5        -
15   10       2
18   10       1

The jQuery file:

$("#items").sortable({
      update: function() {
         var invId = $("input[name='deleteId']").val();
         var post = $(this).sortable('serialize');

         $.ajax({
            type: 'POST',
            url: 'file.php',
            data: { positions: post, id: invId },
            dataType: 'JSON',
            cache: false,
            success: function(output) {
               console.log('success');
            },
            error: function(output) {
               console.log('fail ');
            }
         });
      }
   });

Thanks.

Sergio
  • 792
  • 3
  • 10
  • 35

4 Answers4

0

Your query updates all rows with groupId = 10 each time through the loop, so at the end they will all contain the value from the last element of the array.

You need to write a query that gets a row number for each matching row in the table, and then updates only that row. You can use a user-defined variable to increment the row number.

UPDATE items AS i1
JOIN (SELECT id, @rownum := rownum + 1 AS rownum
      FROM (SELECT id
            FROM items
            WHERE groupId = '$id'
            ORDER BY id) AS i
      CROSS JOIN (SELECT @rownum := 0) AS var) AS i2
ON i1.id = i2.id
JOIN (SELECT 1 AS target, 0 AS val
      UNION ALL
      SELECT 2, 3
      UNION ALL
      SELECT 3, 2
      UNION
      SELECT 4, 1) AS newpos
ON newpos.target = i2.rownum
SET i1.position = newpos.val
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

I think that may be I am missing something, but maybe you should update the items table based on id that matches that specific group id. Something like this:

$id = 10;
$arr = ('0', '3', '2', '1');

$searchId = "SELECT id FROM items WHERE groupId = '$id'";
$result = $db->query($searchId);

foreach($arr as $r) {
   $row = $result->fetch_assoc();
   $sql = " UPDATE items
            SET   position = '$r'
            WHERE id = '{$row['id']}' ";
}

I assumed you use mysqli to connect to your database.

oniramarf
  • 843
  • 1
  • 11
  • 27
  • 1
    not what I was looking for. More like UPDATE items['$r'] if this makes sense... for item[0] SET position = [0], item[1] SET position = [3], etc etc – Sergio Jun 19 '17 at 22:06
  • If I understood it right, @RubenVincenten solved your problem. – oniramarf Jun 19 '17 at 22:47
0

jQuery Sortable should already post data where the values are the row ids and the keys the order. That way, you can do a foreach loop. Assuming the following data:

//$_POST (use chrome inspector to see what post data is being sent)
//positions[] = 3
//positions[] = 18  
//positions[] = 15  
//positions[] = 8  

// note: use a prepared statement, this is just to demonstrate the query.
foreach($_POST['positions'] as $i => $id) {
    $db->query('update table set position = ? where id = ? ',array($i, $id));
}
Ruben Vincenten
  • 807
  • 4
  • 7
  • I stripped/replaced all the row ids down to just the numbers in jquery. So I'm sending to PHP a JSON object containing the array of ids comma separated. And that's what the var $arr in my example would store - something like $arr = $_POST['positions']; I can see the data being sent to and from the PHP file, and it is maintaining the correct order. In the PHP side I can't figure out how to store them in the desired order/place. – Sergio Jun 19 '17 at 21:55
  • Why are you stripping the id's? If a valid reason, why did you omit the code that is stripping them? PHP might receive an order, but how does it know what position to bind to what row? – Ruben Vincenten Jun 19 '17 at 21:58
  • I just assumed it would of been easier to work with just a set of numbers in PHP versus this output from the serialize method - sort[]=0, sort[]=1 etc etc – Sergio Jun 19 '17 at 22:01
  • 1
    Updated my post. If you use the original serialized string, the comments are what you get. – Ruben Vincenten Jun 19 '17 at 22:08
  • I have tried your method but nothing updates in the databse and I get the following error in the developer tools network tab - Warning: Invalid argument supplied for foreach(). I also changed the sortable function in js to use serialize and I am not stripping anything. So what is being sent to PHP is the following sort[]=0&sort[]=1&sort[]=2&sort[]=3 etc etc. Am I missing something?? Thank you! – Sergio Jun 20 '17 at 12:52
  • The values in sort, are they the positions or are they the ids? Also, have changed the post key? I added positions but that isnt going to work obviously. – Ruben Vincenten Jun 20 '17 at 13:22
  • The values in sort are the positions. When it transfers over to PHP it comes in as a string - sort[]=0&sort[]=1&sort[]=2&sort[]=3, I'm failing to understand why would the foreach iterate through them since it will always be 1... 1 string. Even if I explode the string it will still be one array with one key value pair. I'm not sure I understand what you mean by - Also, have changed the post key – Sergio Jun 20 '17 at 13:43
  • I've updated my initial question to include the jquery portion and also included the POST request in the PHP variables. – Sergio Jun 20 '17 at 13:53
  • Ruben, I have added a more in depth and example on here https://stackoverflow.com/questions/44679371/jquery-sortable-saving-to-database-not-working-properly Any inout it would be helpful. Thank you! – Sergio Jun 21 '17 at 15:07
0

If anyone lands on here with similar issues, this is what worked for me.

UPDATE PHP FILE:

$isNum = false;

foreach( $_POST['sort'] as $key => $value ) {
    if ( ctype_digit($value) ) {
        $isNum = true;
    } else {
        $isNum = false;
    }
}

if( isset($_POST) && $isNum == true ){
    require_once('con.php');
   $orderArr = $_POST['sort'];
    $order = 0;
    if ($stmt = $db->prepare(" UPDATE items SET position = ? WHERE id=? ")) {
        foreach ( $orderArr as $item) {
            $stmt->bind_param("ii", $order, $item);
            $stmt->execute();
            $order++;
        }
        $stmt->close();
    }
    echo json_encode(  $orderArr );
    $db->close();
}

JQUERY SORTABLE FILE:

var sortable = $('#items');
   sortable.sortable({
      opacity: 0.325,
      tolerance: 'pointer',
      cursor: 'move',
      update: function(event, ui) {
         var post_data = sortable.sortable('serialize');

         $.ajax({
            type: 'POST',
            url: 'save.php',
            data: post_data,
            dataType: 'json',
            cache: false,
            success: function(output) {
               console.log('success -> ' + output);
            },
            error: function(output) {
               console.log('fail -> ' + output);
            }
         });

      }
   });
   sortable.disableSelection();
Sergio
  • 792
  • 3
  • 10
  • 35