2015-10-20 86 views
0

假設我有一個對象$foo,並且我在字符串變量$bar中有一個參數的名稱。PHP - 變量變量的替代品

我知道我可以使用$foo->$bar訪問參數的值,但我聽說這是一種糟糕的性能方式。

因此我的問題是:有沒有更好的方法來做到這一點?

+2

它只會如果你每秒鐘做這幾百萬次,是一個問題。不過,這並不重要,你不應該過時。也就是說,如果性能是一個問題,步驟1是升級到PHP7。 –

+0

只需直接訪問該屬性? – Dale

+0

@NiettheDarkAbsol實際上它更多的是一種真正需要的好奇心。只是想知道是否有更好的方法來做到這一點 – marcosh

回答

0

真的不要過度想象它。如果屬性名稱是動態生成的,並且您事先不知道它的值,那麼訪問它的唯一方法是$obj->$prop。我想不出爲什麼這會影響性能。

2

首先,我應該說我同意這篇文章中的其他地方的觀點,認爲這可能不是一種值得您花時間的優化。但是,我喜歡SO,因爲它促進了好奇心。爲了滿足這種好奇心,我編寫了一個小型基準測試程序,比較$foo->$bar與想到的第一個替代方案:$foo->someKnownArrayProperty[$bar]。結果表明,第一個速度一直快10%左右。我以1M次迭代測試了幾次運行,然後在10M處測試了幾次。這是我非常簡陋代碼:

<?php 
$iterations = 10000000; 
$bar = 'someproperty'; 
class Foo { 

} 
$foo = new Foo(); 
$start = microtime(TRUE); 
for($i = 0; $i<$iterations; $i++) { 
    $rand = rand(1,1000); 
    $foo->$bar = $rand; 
    if($foo->$bar != $rand) { 
    throw new Exception("A problem occurred reading or writing $bar"); 
    } 
} 
$end = microtime(TRUE); 
$varproptime = $end - $start; 
unset($foo); 
$foo = new Foo(); 
$start = microtime(TRUE); 

$foo->myarray = array(); 
for($i = 0; $i<$iterations; $i++) { 
    $rand = rand(1,1000); 
    $foo->myarray[$bar] = $rand; 
    if($foo->myarray[$bar] != $rand) { 
    throw new Exception("A problem occurred reading or writing $bar"); 
    } 
} 
$end = microtime(TRUE); 
$arrayproptime = $end - $start; 
printf("Variable Property: %f.4\nArray Property: %f.4\n", $varproptime, $arrayproptime); 

一般情況下,我得到約1.0和1.1秒1M迭代,以及10和11秒10M。

編輯

我走得更遠一點與其他的想法:我們可以「編譯」一類與「天然」屬性,有一個setter &的getter。這只是我腦海中浮現的另一個想法。事實證明,對於性能來說這很糟糕,我想象因爲我們需要添加一個框架(使用setter和getters而不是直接訪問)。我需要添加它們的原因是,如果這個想法的目標是在迭代開始後允許所有的代碼都是「靜態」的。基本上,我通過eval()運行了一個類定義,它應該使程序處於一個與使用屬性名稱進行硬編碼相同的狀態。例如,如果您在編程時不知道屬性名稱,但在請求時它恰好是一個值並讀取/寫入許多次,則這個想法很有價值。我認爲如果導致更快的訪問模式,可能會抵消更長的「啓動時間」。但事實並非如此。這大約慢了100%。

$classDefinition = <<<EOD 
class FOO { 
    public \$$bar; 
    function setThatThing(\$value) { 
    \$this->$bar = \$value; 
    } 
    function getThatThing() { 
    return \$this->$bar; 
    } 
EOD; 
eval($classDefinition); 

在執行時,它看起來像這樣(請注意一些$被轉義,有些沒有)

class FOO { 
    public $someproperty; 
    public function setThatThing($value) { 
    $this->someproperty = $value; 
    } 
    public function getThatThing() { 
    return $this->someproperty; 
    } 
}