Выделение массива с числовыми ключами в качестве объекта
Я ткнулся с механизмом кастования 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 находятся в объекте, или просто заблокирован для остальной части жизненного цикла запроса? (практическое использование этого - ноль, мне просто интересно)
Ответы
Ответ 1
Да, они просто заперты, если они не возвращаются к массиву. В 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);
Ответ 2
Похоже, что класс ArrayObject может получить доступ к свойствам
$a = new ArrayObject($obj);
echo $a[0];
Ответ 3
Да, они просто заперты, если они не возвращаются к массиву.
Возможно, свойства все еще существуют и доступны, а не напрямую. Тем не менее, я не уверен, как 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 )
Ответ 4
Я думаю, что вы получили сообщение об ошибке, потому что приведение целочисленного ключа в массив к объекту/подобъекту приведет к нарушению соглашений об именах PHP-переменных.
Советов:
- Решите перед руками, хотите ли вы иметь
OBJECT
или ARRAY
- Будьте осторожны с типом casting (например, (object) array (1 = > 'string') не выполняйте такие вещи)
- Использовать отливки для проверки, а не для преобразования вещей
- Избегайте использования объектов в качестве "поддельных" массивов