Объекты PHP с переменными Int


Я заметил нечто довольно странное с объектами PHP и не могу найти документально подтвержденную причину этого.

Следующий код демонстрирует поведение

<?php
$a = (object) array( 0 => 1 );
foreach($a as $b => $c) {
  $a->$b = ++$c;  //I'm expecting the key to be overwritten here
}
var_dump($a);
$var = 0;
var_dump($a->$var);
$var = "0";
var_dump($a->$var);

И вывод

object(stdClass)#1 (2) {
  [0]=>
  int(1)
  ["0"]=>
  int(2)
}
int(2)
int(2)

Является ли числовая часть класса недоступной с помощью синтаксиса ->?

 6
Author: peter-b, 2014-11-25

2 answers

Когда вы выполняете приведение (object) к массиву, вы продвигаете этот массив как внутренний список свойств анонимного объекта (т.Е. stdClass).

Способ индексирования свойств в объекте немного отличается от способа индексирования массива; в частности, имена свойств объектов всегда обрабатываются как строки, тогда как индексы массива просматриваются на основе предполагаемого типа (например, числовые строки рассматриваются как целые числа).

Описанное выше поведение не влияет на циклы foreach, потому что там нет никакого хэширования; что касается PHP, то повторяется обычный массив.

Чтобы ответить на ваш вопрос, да, цифровые клавиши из вашего исходного массива недоступны с помощью оператора ->. Чтобы избежать этого, вам следует удалить числовые индексы из массива перед выполнением приведения.

Трудно найти такое поведение в документации, но намек на это можно найти здесь:

Если объект преобразуется в массив, в результате получается массив, элементами которого являются свойства объекта. Ключи - это имена переменных-членов, за несколькими заметными исключениями: целочисленные свойства недоступны...

К ВАШЕМУ СВЕДЕНИЮ

В данном конкретном случае вы можете обойти проблему, используя ссылки; это не рекомендуется, пожалуйста, следуйте предыдущему совету не использовать числовые имена свойств:

foreach ($a as &$c) {
    ++$c;
}
unset($c);

Обновление

2014-11-26: Я обновил документацию; живые страницы будут обновлены в эту пятницу - совершить.

 5
Author: Ja͢ck, 2014-11-25 23:29:28

stdClass обрабатывает данные ужасно свободно, так как это объектное представление внутреннего массива (таким образом, возможность приведения без проблем).

$stdClassObject->property = "value";

Свойство обрабатывается как строка, но при приведении тип свойства не меняется (что как-то понятно, как если бы вы приводили к объекту, а затем снова к массиву, вы бы потеряли все целочисленные индексы).

Я не думаю, что они могли бы сделать лучше, чем это, но вы можете создать свою собственную альтернативу Стандартный класс:-)

 1
Author: Shotgun, 2014-11-25 13:01:51