Wednesday, November 11, 2015

PHP: Convert qua lại giữa object và array nhiều cấp

Trong PHP, việc convert qua lại giữa objectarray được thực hiện khá đơn giản thông qua việc cast kiểu
Ex:
$array = (array) $object;
$object = (object) $array;
Tuy nhiên, đối với array nhiều cấp thì việc này chỉ có duy nhất cấp đầu tiên được convert.

Cụ thể, ta có array và tiến hành cast nó qua object:
$arr = [
    'tier1_a' => 'a',
    'tier1_b' => [
        'tier2_c' => 'c',
        'tier2_d' => 'd'
    ]
];

var_dump($arr);
var_dump((object) $arr);
Kết qủa nhận được là:
array(2) {
  ["tier1_a"]=>
  string(1) "a"
  ["tier1_b"]=>
  array(2) {
    ["tier2_c"]=>
    string(1) "c"
    ["tier2_d"]=>
    string(1) "d"
  }
}
object(stdClass)#1 (2) {
  ["tier1_a"]=>
  string(1) "a"
  ["tier1_b"]=>
  array(2) {
    ["tier2_c"]=>
    string(1) "c"
    ["tier2_d"]=>
    string(1) "d"
  }
}
Có thể thấy cấp đầu tiên đã được cast sang object nhưng cấp thứ 2 vẫn là array.

Tại sao casting không work với trường hợp array nhiều cấp?

Đoạn này diễn đạt hơi khó hiểu chút nhưng nôm na là:
Vì casting chỉ làm việc với bản thân variable đó (ở ví dụ trên là $arr) chứ không làm việc với nội dung của biến đó (các props (tier1_a, tier1_b)) nên nội dung bên trong không bị casting tác động đến.
Nói tóm lại casting sẽ không làm việc với recursively subarray. Để solve vấn đề này có một vài cách, tuy nhiên đơn giản nhất có thể sử dụng JSON function.

Array to Object

Chỉ việc sử dụng đồng thời json_encodejson_decode để convert:
var_dump(json_decode(json_encode($arr)));
Và bây giờ array nhiều cấp đã được convert thành object hoàn toàn:
object(stdClass)#1 (2) {
  ["tier1_a"]=>
  string(1) "a"
  ["tier1_b"]=>
  object(stdClass)#2 (2) {
    ["tier2_c"]=>
    string(1) "c"
    ["tier2_d"]=>
    string(1) "d"
  }
}

Object to Array

Để convert hoàn toàn object nhiều cấp sang array thì chỉ việc pass thêm tham số $assoc = TRUE
var_dump(json_decode(json_encode($arr), true));
Kết qủa:
array(2) {
  ["tier1_a"]=>
  string(1) "a"
  ["tier1_b"]=>
  array(2) {
    ["tier2_c"]=>
    string(1) "c"
    ["tier2_d"]=>
    string(1) "d"
  }
}

No comments:

Post a Comment