使用数字键作为对象转换数组

时间:2009-12-08 21:01:53

标签: php arrays casting

我正在探讨PHP的构建机制,并在将数组作为对象进行投射时遇到了奇怪的情况

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

据我了解,PHP属性需要使用与PHP变量相同的规则声明。那是A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores。但是,上面的代码产生以下输出

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报告的信息在对象中,还是只是在请求生命周期的其余部分被锁定? (实际使用这是零,我只是好奇)

4 个答案:

答案 0 :(得分:14)

是的,他们只是被锁定,除非被强制转换回阵列。在PHP中有一些小的“陷阱”,例如在旧版本中,您可以将常量定义为数组,但从不访问其元素。即使是现在,您也可以将常量定义为资源(​​例如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;
}
编辑:只是对这个假设进行了一次快速测试,是的,它们在对象上下文中正式“不存在”;数据存储,但无法访问,因此是最终的私人成员。这是测试:

$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);

答案 1 :(得分:7)

似乎ArrayObject类可以访问属性

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

答案 2 :(得分:1)

  

是的,除非被投回阵列,否则它们只会被锁定。

也许,这些属性仍然存在且可以访问,而不是直接访问。但是,我不确定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 )

答案 3 :(得分:0)

我认为你得到一个错误,因为将一个数组的整数键转换为一个对象/子对象将破坏PHP varibles的命名约定。

提示:

  • 事先决定是否要OBJECTARRAY
  • 注意类型转换(例如(对象)数组(1 =&gt;'string')不要做这样的事情)
  • 使用石膏进行验证而不是转换物品
  • 避免将对象用作“假”数组