0

I get msg_data from MySQL query with ORDER BY msg_time clause. I use then use foreach loop to create JS object of objects like this:

<script type="text/javascript">
    var active_swaps = {
    <?php if (is_array($msg_data) || $msg_data instanceof Traversable):?>
        <?php foreach($msg_data as $msg_item):?>
            <?php echo $msg_item['id'];?> : <?php echo json_encode($msg_item);?>,
        <?php endforeach;?>
    <?php endif;?>
    };
</script>

if I check $msg_data with var_dump I get:

array (size=3)
  0 => 
    array (size=20)
      'id' => string '5' (length=1)
      'user1_id' => string '1' (length=1)
      'user2_id' => string '2' (length=1)
      'hasto' => string '2' (length=1)
      'requested' => string '2017-01-20 14:28:00' (length=19)
      'accepted' => null
      'swapped1' => null
      'swapped2' => null
      'rejected' => null
      'rejected_by' => null
      'swap_seen' => null
      'msg_id' => string '23' (length=2)
      'sender_id' => string '1' (length=1)
      'msg' => string 'awdwadwd' (length=8)
      'msg_time' => string '2017-01-20 15:58:06' (length=19)
      'swap_id' => string '5' (length=1)
      'seen' => null
      'user1username' => string 'user1' (length=5)
      'user2username' => string 'user2' (length=5)
      'online' => string 'false' (length=5)
  1 => 
    array (size=20)
      'id' => string '7' (length=1)
      'user1_id' => string '1' (length=1)
      'user2_id' => string '2' (length=1)
      'hasto' => string '2' (length=1)
      'requested' => string '2017-01-20 15:57:51' (length=19)
      'accepted' => null
      'swapped1' => null
      'swapped2' => null
      'rejected' => null
      'rejected_by' => null
      'swap_seen' => null
      'msg_id' => string '22' (length=2)
      'sender_id' => string '1' (length=1)
      'msg' => string 'awdawd' (length=6)
      'msg_time' => string '2017-01-20 15:58:00' (length=19)
      'swap_id' => string '7' (length=1)
      'seen' => null
      'user1username' => string 'user1' (length=5)
      'user2username' => string 'user2' (length=5)
      'online' => string 'false' (length=5)
  2 => 
    array (size=20)
      'id' => string '6' (length=1)
      'user1_id' => string '1' (length=1)
      'user2_id' => string '2' (length=1)
      'hasto' => string '2' (length=1)
      'requested' => string '2017-01-20 15:11:58' (length=19)
      'accepted' => null
      'swapped1' => null
      'swapped2' => null
      'rejected' => null
      'rejected_by' => null
      'swap_seen' => null
      'msg_id' => string '20' (length=2)
      'sender_id' => string '1' (length=1)
      'msg' => string 'awdadwdwa' (length=9)
      'msg_time' => string '2017-01-20 15:46:44' (length=19)
      'swap_id' => string '6' (length=1)
      'seen' => null
      'user1username' => string 'user1' (length=5)
      'user2username' => string 'user2' (length=5)
      'online' => string 'false' (length=5)

However in JS console.log(active_swaps); returns this:

Object {5: Object, 6: Object, 7: Object}

No matter what I do it is always sorted by key(swap_id)! Would appreciate if someone could explain why is that happening?

Kārlis Janisels
  • 1,055
  • 2
  • 12
  • 30
  • Maybe it is not so good to use `numbers` for json object properties!? Test it with `echo "id{$msg_item['id']}";`. – JustOnUnderMillions Jan 20 '17 at 16:11
  • The order of properties in a javascript object *are not guaranteed*: http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – random_user_name Jan 20 '17 at 16:14
  • 2
    Possible duplicate of [Does JavaScript Guarantee Object Property Order?](http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order) – random_user_name Jan 20 '17 at 16:14
  • Thanks everybody for pointing out the real issue. In one of answer I wound this: `Current Browsers: order is preserved with the major exception of keys like "7" that parse as integers and are handled differently by Chrome/V8.`. Are there any more reasons to not use integers as keys? If I find another solution for order, can I use integers as keys? – Kārlis Janisels Jan 20 '17 at 16:38

1 Answers1

0

Well, it looks like you're creating an object with $msg_item['id'] as key :

var active_swaps = {
<?php if (is_array($msg_data) || $msg_data instanceof Traversable):?>
    <?php foreach($msg_data as $msg_item):?>
        <?php echo $msg_item['id'];?> : <?php echo json_encode($msg_item);?>,
    <?php endforeach;?>
<?php endif;?>
};

is interpreted in your loop as :

var active_swaps = {
    5 : 'JSON Object',
    6 : 'JSON Object',
    7 : 'JSON Object',
};

(Nota : I replaced here the actual JSON string by 'JSON Object' for readability)

You should create an array instead of an object (which means numeric and 0-indexed keys (Thanks to @CharlotteDunois for pointing that out)), as such :

var active_swaps = [];
<?php if (is_array($msg_data) || $msg_data instanceof Traversable):?>
    <?php foreach($msg_data as $msg_item):?>
        active_swaps.push(<?php echo json_encode($msg_item);?>);
    <?php endforeach;?>
<?php endif;?>

Which would be equivalent to :

var active_swaps = [];
active_swaps.push('JSON Object');
active_swaps.push('JSON Object');
active_swaps.push('JSON Object');

Then console.log(active_swaps) should return the following :

[Object, Object, Object]

EDIT : Keeping the output as an object

You could use the key of your $msg_data as your JS Object key :

var active_swaps = {
<?php if (is_array($msg_data) || $msg_data instanceof Traversable):?>
    <?php foreach($msg_data as $key=>$msg_item):?>
        <?php echo $key;?> : <?php echo json_encode($msg_item);?>,
    <?php endforeach;?>
<?php endif;?>
};

The output of console.log(active_swaps) would now be Object {0: Object, 1: Object, 2: Object}, supposedly keeping the same order as your PHP array (ie 5, then 7, then 6)

roberto06
  • 3,817
  • 1
  • 17
  • 29
  • 1
    That arrays don't have keys is actually false. They have keys, but they are numeric and 0-indexed. – Charlotte Dunois Jan 20 '17 at 16:14
  • further, this question is actually a duplicate. Please vote to close (if you choose "duplicate", the already-selected-by-another-user duplicate is already listed for you, so you don't have to find it). – random_user_name Jan 20 '17 at 16:15
  • @CharlotteDunois Sorry, that's what I meant. – roberto06 Jan 20 '17 at 16:15
  • While this works I need object not array. @ JustOnUnderMillions comment is correct. – Kārlis Janisels Jan 20 '17 at 16:17
  • Well, you could also use an object with numeric and 0-defined keys. Or with any other key that you'd like.What I was trying to demonstrate here is that the keys of your JS object are identical to `$msg_item['id']` because, in your loop, that's the value you're setting to the keys. – roberto06 Jan 20 '17 at 16:21
  • @KārlisJanisels I edited my answer with a snippet for creating an object, (supposedly) keeping the PHP array order, please check it out. – roberto06 Jan 20 '17 at 16:25
  • Sorry, meybe I have not explained myself correctly. I need those keys to be reference to swap_id. I want to use it like active_swaps[swap_id].requested – Kārlis Janisels Jan 20 '17 at 16:35