2009-12-08 35 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)