krakjoe/pthreads

Volatile coercion does strange things to numeric array keys

dktapps opened this issue · 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}"

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));

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.

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]"