pthreads icon indicating copy to clipboard operation
pthreads copied to clipboard

Volatile coercion does strange things to numeric array keys

Open dktapps opened this issue 7 years ago • 3 comments

Environment

  • PHP: 7.2.9
  • pthreads: master
  • OS: windows

Reproducing Code

$data = [1, 2, 3, 4, 5];

$threaded = new \Threaded;
$threaded->data = $data;

var_dump(json_encode($data));
var_dump(json_encode($threaded->data));

Expected Output

string(11) "[1,2,3,4,5]"
string(11) "[1,2,3,4,5]"

Actual Output

string(11) "[1,2,3,4,5]"
string(31) "{"0":1,"1":2,"2":3,"3":4,"4":5}"

dktapps avatar Sep 21 '18 14:09 dktapps

Hey @dktapps, this is an expected behavior, albeit getting used to. After the assignment of $data, $threaded->data is a Volatile object with key/value properties and no array anymore. So json_encode() handles $threaded->data like an object. That can be prevented by doing an explicit cast back to array at the passing of $threaded->data:

$data = [1, 2, 3, 4, 5];

$threaded = new \Threaded;
$threaded->data = $data;

var_dump(json_encode($data));
var_dump(json_encode((array)$threaded->data));

Alternatively, a cast is possible during the assignment, but not recommended because of serialization / deserialization in the background

$data = [1, 2, 3, 4, 5];

$threaded = new \Threaded;
$threaded->data = (array)$data;

var_dump(json_encode($data));
var_dump(json_encode($threaded->data));

sirsnyder avatar Sep 24 '18 01:09 sirsnyder

Yep. The reason I made this issue is because it's a confusing behaviour that I see often developers getting confused with, nobody thinks to check if an array is getting coerced by their async tasks. It is not particularly intuitive, so it would be good if there was a way to solve this.

dktapps avatar Sep 24 '18 07:09 dktapps

Additionally, casting to array does not produce the expected output - and also may be a problem for nested arrays (my guys are trying to async post Discord webhook data, so this is a common problem):

<?php

$t = new Threaded;
$a = [1, 2, [3, 4], 5];

$t->a = $a;
var_dump(json_encode((array) $t->a));
var_dump(json_encode($a));

outputs

string(37) "{"2":{"0":3,"1":4},"0":1,"1":2,"3":5}"
string(13) "[1,2,[3,4],5]"

dktapps avatar Sep 24 '18 07:09 dktapps