2009-12-08 49 views
12

我闲逛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报告中的信息是在对象,或者它只是锁定为请求生命周期的休息吗? (这实际使用中是零,我只是好奇)

+0

从我的经验看来,他们都锁起来,虽然我从来没有足够的坚定尝试一切。 – jlb 2009-12-08 21:05:33

+0

事实上,这是PHP中的一个已知问题。 – GSto 2009-12-08 21:38:38

+0

这就是我们所知道的,或者被PHP团队以某种方式称为已知的。 – 2009-12-08 21:45:17

回答

13

是的,他们只是锁定了,除非施法回阵列。 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; 
} 

编辑:只是做了一个更快速测试这一假设,是的,他们在对象语境中正式“不存在”;数据被存储,但不可能访问,因此是最终的私人成员。下面是测试:

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

,输出是:

bool(false) 
bool(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

这实际上是一个[bug](https://bugs.php.net/bug.php?id=45959)。它被认为“修理费用太高”,而且解决方案已经“更新了文档来描述这种无用的怪癖,所以现在它是正式的正确行为”。 – lanzz 2012-06-23 22:04:58

0

我想你因为将数组的整数键转换为对象/子对象将会破坏PHP变量的命名约定。

提示:

  • 你是否想有一个OBJECTARRAY
  • 小心型铸造手之前决定(例如,(对象)阵列(1 =>“串”)不要做这样的事情)
  • 进行验证使用铸件和不转换的东西
  • 避免使用对象为“假”阵列
7

看来,ArrayObject的类可以访问属性

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

这非常方便。谢谢! – SuitedSloth 2012-10-18 19:11:49

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)