Подтвердить что ты не робот

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

Я ткнулся с механизмом кастования 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 находятся в объекте, или просто заблокирован для остальной части жизненного цикла запроса? (практическое использование этого - ноль, мне просто интересно)

4b9b3361

Ответ 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') не выполняйте такие вещи)
  • Использовать отливки для проверки, а не для преобразования вещей
  • Избегайте использования объектов в качестве "поддельных" массивов