Je me promenais donc dans php.net pour obtenir des informations sur la sérialisation des objets PHP en JSON, lorsque je suis tombé sur la nouvelle interface JsonSerializable . C'est seulement PHP> = 5.4 cependant, et j'exécute dans un environnement 5.3.x.
Comment ce type de fonctionnalité est-il réalisé? PHP <5.4 ?
Je n'ai pas encore beaucoup travaillé avec JSON, mais j'essaie de prendre en charge une couche API dans une application et de vider l'objet de données ( qui serait autrement envoyé à la vue ) dans JSON serait parfait.
Si j'essaye de sérialiser l'objet directement, il renvoie une chaîne JSON vide; qui est parce que je suppose json_encode()
ne sait pas ce que diable faire avec l'objet. Dois-je réduire récursivement l'objet dans un tableau, puis encoder cela ?
Exemple
$data = new Mf_Data();
$data->foo->bar['hello'] = 'world';
echo json_encode($data)
produit un objet vide:
{}
var_dump($data)
cependant, fonctionne comme prévu:
object(Mf_Data)#1 (5) {
["_values":"Mf_Data":private]=>
array(0) {
}
["_children":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["foo"]=>
object(Mf_Data)#2 (5) {
["_values":"Mf_Data":private]=>
array(0) {
}
["_children":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["bar"]=>
object(Mf_Data)#3 (5) {
["_values":"Mf_Data":private]=>
array(1) {
[0]=>
array(1) {
["hello"]=>
string(5) "world"
}
}
["_children":"Mf_Data":private]=>
array(0) {
}
["_parent":"Mf_Data":private]=>
*RECURSION*
["_key":"Mf_Data":private]=>
string(3) "bar"
["_index":"Mf_Data":private]=>
int(0)
}
}
}
["_parent":"Mf_Data":private]=>
*RECURSION*
["_key":"Mf_Data":private]=>
string(3) "foo"
["_index":"Mf_Data":private]=>
int(0)
}
}
}
["_parent":"Mf_Data":private]=>
NULL
["_key":"Mf_Data":private]=>
NULL
["_index":"Mf_Data":private]=>
int(0)
}
Addenda
1)
toArray()
Voici donc la fonction que j'ai conçue pour la Mf_Data
classe:
public function toArray()
{
$array = (array) $this;
array_walk_recursive($array, function (&$property) {
if ($property instanceof Mf_Data) {
$property = $property->toArray();
}
});
return $array;
}
Cependant, comme les Mf_Data
objets ont également une référence à leur objet parent ( contenant ), cela échoue avec la récursivité. Fonctionne comme un charme quand je supprime la _parent
référence.
2)
Juste pour faire un suivi, la fonction finale pour transformer un objet complexe de nœud d'arbre avec lequel je suis allé était:
// class name - Mf_Data
// exlcuded properties - $_parent, $_index
public function toArray()
{
$array = get_object_vars($this);
unset($array['_parent'], $array['_index']);
array_walk_recursive($array, function (&$property) {
if (is_object($property) && method_exists($property, 'toArray')) {
$property = $property->toArray();
}
});
return $array;
}
3)
Je fais un suivi à nouveau, avec une mise en œuvre un peu plus claire. L'utilisation d'interfaces pour une instanceof
vérification semble beaucoup plus propre que method_exists()
( cependant l' method_exists()
héritage / l'implémentation croisée ).
L'utilisation unset()
semblait aussi un peu compliquée, et il semble que la logique devrait être refactorisée dans une autre méthode. Toutefois, cette mise en œuvre ne copier le tableau de la propriété ( en raison dearray_diff_key
), donc quelque chose à considérer.
interface ToMapInterface
{
function toMap();
function getToMapProperties();
}
class Node implements ToMapInterface
{
private $index;
private $parent;
private $values = array();
public function toMap()
{
$array = $this->getToMapProperties();
array_walk_recursive($array, function (&$value) {
if ($value instanceof ToMapInterface) {
$value = $value->toMap();
}
});
return $array;
}
public function getToMapProperties()
{
return array_diff_key(get_object_vars($this), array_flip(array(
'index', 'parent'
)));
}
}
JsonSerializable