Cập nhật cho PHP 7.2
PHP 7.2 đã giới thiệu một thay đổi hành vi để chuyển đổi các khóa số trong các phôi đối tượng và mảng , giúp khắc phục sự không nhất quán cụ thể này và làm cho tất cả các ví dụ sau hoạt động như mong đợi.
Một điều ít hơn để được nhầm lẫn về!
Câu trả lời gốc (áp dụng cho các phiên bản trước 7.2.0)
PHP có những con hẻm tối tăm mà bạn thực sự không muốn tìm thấy mình bên trong. Thuộc tính đối tượng có tên là số là một trong số chúng ...
Điều họ chưa bao giờ nói với bạn
Sự thật số 1: Bạn không thể dễ dàng truy cập các thuộc tính có tên không phải là tên biến hợp pháp
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo;
Sự thật # 2: Bạn có thể truy cập các thuộc tính như vậy bằng cú pháp dấu ngoặc nhọn
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'};
Sự thật thứ 3: Nhưng không phải nếu tên tài sản là tất cả các chữ số!
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'};
echo $o->{'123'};
Ví dụ trực tiếp .
Sự thật thứ 4: Chà, trừ khi đối tượng không đến từ một mảng ngay từ đầu.
$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123';
echo $o1->{'123'};
echo $o2->{'123'};
Ví dụ trực tiếp .
Khá trực quan, bạn có đồng ý không?
Bạn có thể làm gì
Tùy chọn số 1: làm thủ công
Cách tiếp cận thực tế nhất chỉ đơn giản là truyền đối tượng bạn quan tâm trở lại vào một mảng, điều này sẽ cho phép bạn truy cập các thuộc tính:
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'};
echo $a['123'];
Thật không may, điều này không hoạt động một cách đệ quy. Vì vậy, trong trường hợp của bạn, bạn cần phải làm điều gì đó như:
$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0'];
Tùy chọn số 2: tùy chọn hạt nhân
Một cách tiếp cận thay thế sẽ là viết một hàm chuyển đổi các đối tượng thành mảng một cách đệ quy:
function recursive_cast_to_array($o) {
$a = (array)$o;
foreach ($a as &$value) {
if (is_object($value)) {
$value = recursive_cast_to_array($value);
}
}
return $a;
}
$arr = recursive_cast_to_array($myVar);
$value = $arr['highlighting']['448364']['Data']['0'];
Tuy nhiên, tôi không tin rằng đây là một lựa chọn tốt hơn trên toàn diện bởi vì nó sẽ không cần thiết truyền sang mảng tất cả các thuộc tính mà bạn không quan tâm cũng như những thuộc tính bạn đang có.
Tùy chọn # 3: Chơi thông minh
Một lựa chọn thay thế cho tùy chọn trước đó là sử dụng các hàm JSON được tích hợp sẵn:
$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];
Các hàm JSON thực hiện một cách hữu ích việc chuyển đổi đệ quy sang mảng mà không cần xác định bất kỳ hàm bên ngoài nào. Tuy nhiên, điều này trông mong muốn, nó có nhược điểm "nuke" của tùy chọn số 2 và thêm vào đó là nhược điểm là nếu có bất kỳ chuỗi nào bên trong đối tượng của bạn, các chuỗi đó phải được mã hóa bằng UTF-8 (đây là một yêu cầu của json_encode
).