Hi, im using
PHP 7.0.4-7ubuntu2 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
And
Laravel Framework version 5.1.34 (LTS)
When giving the below value to json_encode it is returning false rather than string
Illuminate\Database\Eloquent\Collection {#3502
all: [
App\User {#3487
last_active: "",
},
],
}
but it is returning correct string in php5-fpm.
two days back only i upgraded to php7 and observed this error.
Please report this bug to the PHP team.
The error occurred in Collection class that is specific to laravel rather than PHP team. Im not sure the PHP team is aware of Collection class and its magic methods.
If it worked on PHP 5, and is broken on PHP 7, this is a bug. They did not intend for the json functions to have changed between versions.
Try json_last_error_msg first
Hi @rkgrep , the output is "Syntax error"
@pavankumarkatakam are you sure that json_encode returns that error?
here is a comment on PHP 7 about it, but for json_decode
@pavankumarkatakam do you have JSON casts in the model?
Hi @rkgrep , I have casts enabled in User model, shown below
protected $casts = [
'privileges' => 'json',
'preferences' => 'json',
'access' => 'json',
'last_active' => 'json',
'id' => 'integer',
'family_data_id' => 'integer',
'mobile_verified' => 'boolean',
'email_verified' => 'boolean',
'mobile' => 'integer',
'is_delete' => 'boolean',
'app_storage' => 'json',
'custom_data' => 'json'
];
And mentioning about the column last_active.
Hi @rkgrep , when issuing the command json_encode(["something"=>""]); it returns correct string "{"something":""}" , but when using the Collection item with empty string value it is returning the false.
Collection item in my case
Illuminate\Database\Eloquent\Collection {#3465
all: [
App\User {#3466
last_active: "",
},
],
}
Which is resulted from my query $temp=\App\User::where('id',3)->select('last_active')->get(); .
I hope its clear now. That's the reason i have opened issue here rather than the PHP bug.
@pavankumarkatakam Collection is being converted to array first. With each item converted to array.
What does $collection->toArray() return?
The output when converted to toArray() ,
[
[
"last_active" => null,
"age" => null,
"age_display" => null,
"religion_display" => "",
"country_display" => "",
"country_code_display" => null,
],
]
If the give above input to json_encode it is working fine. shown below
"{"something":[{"last_active":null,"age":null,"age_display":null,"religion_display":"","country_display":"","country_code_display":null}]}"
When explicitly specifying the toArray() on query result (Collection) it is working fine
json_encode(["something"=>\App\User::where('id',2)->select('last_active')->get()->toArray()]);
it returning the "{"something":[{"last_active":null,"age":null,"age_display":null,"religion_display":"","country_display":"","country_code_display":null}]}"
But in my applications (roughly 7 to 8 ) projects i have used to return Collection items in response in many places, i think i want to check all of them and write toArray(); its really a big change i think so.
I think it's related the php bug 72069. If a class implementing JsonSerializable calls json_encode/json_decode in jsonSerialize, and that function fails then it will lead to the failure of encoding the object.
You can try if the latest version from git fix this bug or not.
As a workround, you can use json_encode($obj->jsonSerialize()) instead of json_encode($obj).
or you may modify the Illuminate\Support\Collection->jsonSerialize() to the following codes:
$res = array_map(function ($value) {
if ($value instanceof JsonSerializable) {
return $value->jsonSerialize();
} elseif ($value instanceof Jsonable) {
return json_decode($value->toJson(), true);
} elseif ($value instanceof Arrayable) {
return $value->toArray();
} else {
return $value;
}
}, $this->items);
json_encode([]); //clear the json_last_error
return $res;
Hi @jhdxr , first i installed PHP 7.0.5
PHP 7.0.5-3+donate.sury.org~xenial+1 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
But still the problem exists, after that i changed the Collection class jsonSerialize() function, then its working fine.
@pavankumarkatakam the bug was fixed 4 days age and not released yet. You have to compile the source from git on you own, or you may be have to wait for 7.0.7 out (as 7.0.6 is at rc stage)
Actually im not aware of compiling, so i go with fix in collection for now.
And Thanks for helping.
Hi @jhdxr, if we go with the fix we want to change in all code where there is json_encode(), so i want to compile myself the php, could you please give me instructions to do so.
@pavankumarkatakam Did you change the actual implementation of the jsonSerialize function in the laravel framework core? If you did, then its bad practice. I would suggest creating a simple class to set JSON data. What @jhdxr provided you was the right solution but you shouldn't be changing the core framework code.
I myself am using PHP 7 for one of my side projects. I haven't run into the issue you mentioned.
Hi @srmklive , this is already a bug in the php repo and fixed in the php 7.0.7 version. So im closing it.
Today i installed the php 7.0.7 and this is fixed
Hi @pavankumarkatakam
You said this fixed in 7.0.7 ... I have this issue for 7.0.11 !!!
Well I don't know regarding 7.0.11 , may be they changed want to check in php language repository.
I have the same issue with PHP 5.6.31:
$users = Users::all();
return Response::json($users);
The Response content must be a string or object implementing __toString(), "boolean" given.
False appears when toJson() is called.
Most helpful comment
As a workround, you can use
json_encode($obj->jsonSerialize())instead ofjson_encode($obj).or you may modify the
Illuminate\Support\Collection->jsonSerialize()to the following codes: