Donc, je me promenais autour de php.net pour plus d'informations sur la sérialisation des objets PHP, JSON, quand j'ai trébuché à travers le nouveau JsonSerializable Interface. C'est seulement PHP >= 5.4 si, et je suis en cours d'exécution dans un 5.3.x environnement.
Comment est-ce que ce genre de fonctionnalité atteint PHP < 5.4?
Je n'ai pas beaucoup travaillé avec JSON, mais je suis en train de soutenir une couche API dans une application, et l'immersion de l'objet de données (qui autrement seraient envoyés à l'affichage) en JSON, ce serait parfait.
Si je tente de sérialiser l'objet directement, il renvoie un vide chaîne JSON; c'est parce que je suppose json_encode()
ne sait pas ce que le diable à faire avec l'objet. Dois-je réduire de manière récursive l'objet dans un tableau, et puis l'encoder qui?
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)
}
Addendum
1)
C'est donc l' toArray()
fonction que j'ai conçu pour l' Mf_Data
classe:
public function toArray(){
$array = (array) $this;
array_walk_recursive($array, function(&$property, $key){
if($property instanceof Mf_Data){
$property = $property->toArray();
}
});
return $array;
}
Toutefois, depuis l' Mf_Data
objets ont également une référence à leur parent (contenant) de l'objet, il échoue avec la récursivité. Fonctionne comme un charme, mais quand j'ai enlever l' _parent
de référence.
2)
Juste pour le suivi, la dernière fonction de transformer un complexe d'arbres nœud d'objet, je suis allé avec a:
// 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, $key){
if(is_object($property)
&& method_exists($property, 'toArray')){
$property = $property->toArray();
}
});
return $array;
}
3)
Je suis encore une fois, avec un peu de nettoyant de la mise en œuvre. L'utilisation d'interfaces pour un instanceof
vérifiez semble beaucoup plus propre qu' method_exists()
(toutefois method_exists()
ne transversale sur les droits de succession/mise en œuvre).
À l'aide de unset()
semble un peu brouillon aussi, et il semble que la logique devrait être remaniée en une autre méthode. Toutefois, cette mise en œuvre ne copie la propriété array (due à l' array_diff_key
), donc quelque chose à considérer.
(Aussi, oui, ce n'utiliser PHP 5.4 syntaxe pour des raisons de concision)
interface ToArrayInterface {
function toArray();
function getToArrayProperties();
}
class Node implements ToArrayInterface {
private $index;
private $parent;
private $values = [];
public function toArray() {
$array = $this->getToArrayProperties();
array_walk_recursive($array, function(&$value, $key) {
if ($value instanceof ToArrayInterface) {
$value = $value->toArray();
}
});
return $array;
}
public function getToArrayProperties() {
return array_diff_key(get_object_vars($this), array_flip([
'index', 'parent'
]));
}
}