假設我有一個對象$foo
,並且我在字符串變量$bar
中有一個參數的名稱。PHP - 變量變量的替代品
我知道我可以使用$foo->$bar
訪問參數的值,但我聽說這是一種糟糕的性能方式。
因此我的問題是:有沒有更好的方法來做到這一點?
假設我有一個對象$foo
,並且我在字符串變量$bar
中有一個參數的名稱。PHP - 變量變量的替代品
我知道我可以使用$foo->$bar
訪問參數的值,但我聽說這是一種糟糕的性能方式。
因此我的問題是:有沒有更好的方法來做到這一點?
真的不要過度想象它。如果屬性名稱是動態生成的,並且您事先不知道它的值,那麼訪問它的唯一方法是$obj->$prop
。我想不出爲什麼這會影響性能。
首先,我應該說我同意這篇文章中的其他地方的觀點,認爲這可能不是一種值得您花時間的優化。但是,我喜歡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;
}
}
它只會如果你每秒鐘做這幾百萬次,是一個問題。不過,這並不重要,你不應該過時。也就是說,如果性能是一個問題,步驟1是升級到PHP7。 –
只需直接訪問該屬性? – Dale
@NiettheDarkAbsol實際上它更多的是一種真正需要的好奇心。只是想知道是否有更好的方法來做到這一點 – marcosh