Выделение массива с числовыми ключами в качестве объекта

Я топал вокруг механизма кастования PHP и столкнулся с нечетным случаем при создании массива как объекта

$o = (object) array('1'=>'/foo/bar'); $o = new stdClass(); var_dump($o); 

Насколько я понимаю, свойства PHP должны быть объявлены с теми же правилами, что и переменные PHP. Это допустимое имя переменной начинается с буквы или подчеркивания, за которой следует любое количество букв, цифр или символов подчеркивания . Однако приведенный выше код дает следующий результат

 object(stdClass)#1 (1) { [1]=> string(8) "/foo/bar" } 

Там, где это действительно странно, вы пытаетесь получить доступ к этой информации в объекте.

 var_dump($o->1); // parse error var_dump($o->{'1'}); // NULL var_dump(get_object_vars($o)); //array(0) { } 

В любом случае, чтобы получить информацию о том, что в объекте есть данные var_dump, или просто заблокирован для остальной части жизненного цикла запроса? (практическое использование этого – ноль, мне просто любопытно)

Да, они просто заперты, если они не вернутся к массиву. В PHP есть несколько небольших «Gotchas», например, в более старых версиях вы можете определить константу как массив, но затем никогда не обращаться к ее элементам. Даже сейчас вы можете определить константу как ресурс (например, define('MYSQL',mysql_connect()); ) хотя это приводит к довольно непредсказуемому поведению и, опять же, следует избегать.

Как правило, лучше избегать приведения массива к объекту, если это вообще возможно. Если вам действительно нужно это сделать, подумайте о создании нового экземпляра stdClass а затем вручную переименуйте все переменные, например, в _0 , _1 и т. Д.

 $a = array('cat','dog','pheasant'); $o = new stdClass; foreach ($a as $k => $v) { if (is_numeric($k)) { $k = "_{$k}"; } $o->$k = $v; } 

EDIT: Просто сделал еще один быстрый тест по этой гипотезе, и да, они официально «не существуют» в объектном контексте; данные сохраняются, но доступ к ним невозможно, и поэтому он является конечным частным пользователем. Вот тест:

 $a = array('one','two','three'); $o = (object)$a; var_dump(property_exists($o, 1), property_exists($o, '1')); 

И выход:

 bool(false) bool(false) 

ИЗМЕНИТЬ СНОВА: Интересная заметка, следующая операция возвращается false:

 $a = array('one','two','three','banana' => 'lime'); $b = array('one','two','banana' => 'lime'); $y = (object)$a; $z = (object)$b; var_dump($y == $z); 

Похоже, класс ArrayObject может получить доступ к свойствам

 $a = new ArrayObject($obj); echo $a[0]; 

Да, они просто заперты, если они не вернутся к массиву.

Возможно, свойства все еще существуют и доступны, а не напрямую. Тем не менее, я не уверен, как foreach работает внутри (он может передать объект в массив), поскольку я не погружался в исходный код.

Пример:

 $array = array('one', 'two', 'three', 'four'); $obj = (object) $array; foreach ($obj as $key => &$val) { print "$key -> $val<br>"; $val = 'Nhaca'; var_dump($obj); } print_r($obj); print_r($array); 

вывод:

 0 -> one object(stdClass)[1] &string 'Nhaca' (length=5) string 'two' (length=3) string 'three' (length=5) string 'four' (length=4) 1 -> two object(stdClass)[1] string 'Nhaca' (length=5) &string 'Nhaca' (length=5) string 'three' (length=5) string 'four' (length=4) 2 -> three object(stdClass)[1] string 'Nhaca' (length=5) string 'Nhaca' (length=5) &string 'Nhaca' (length=5) string 'four' (length=4) 3 -> four object(stdClass)[1] string 'Nhaca' (length=5) string 'Nhaca' (length=5) string 'Nhaca' (length=5) &string 'Nhaca' (length=5) stdClass Object ( [0] => Nhaca [1] => Nhaca [2] => Nhaca [3] => Nhaca ) Array ( [0] => one [1] => two [2] => three [3] => four ) 

Я думаю, вы получаете сообщение об ошибке, потому что приведение целочисленного ключа в массив к объекту / подобъекту приведет к нарушению соглашений об именах переменных var var.

Советы:

  • Решите перед руками, хотите ли вы иметь объект OBJECT или ARRAY
  • Будьте осторожны с типом casting (например, (object) array (1 => 'string') не выполняйте такие вещи)
  • Использовать отливки для проверки и не конвертировать вещи
  • Избегайте использования объектов в качестве «поддельных» массивов