我写了__set以确保在setter之前完成某些事情
public function __setter($name, $value) {
if ($this->needDoSomething) {$this->doSomeThingNecessaryBeforeSetAnything();}
$this->needDoSomething = false;
$this->$name = $value;
}
然而,神奇的方法会影响性能。在同一个班级,我有另一个功能
private function loadData() {
if ($this->needDoSomething) {$this->doSomeThingNecessaryBeforeSetAnything();}
foreach ($data as $key=>$value) {
$this->$key = $value;
}
}
由于已经调用了doSomeThingNecessaryBeforeSetAnything(),我不需要调用__set,而是想直接设置属性。这对性能有很大帮助 但是,我无法删除__set,因为类外有很多遗留代码,我需要它来使逻辑正确。
似乎用PHP我无法动态添加或删除对象的方法。有任何想法吗?
编辑:性能是由__set本身引起的,因为我有大量的对象,每个对象都有大量的属性需要设置。下面的代码显示__set比直接设置属性慢6倍。
class Test {}
class Test2 {
public function __set($name, $value) {
$this->$name = $value;
}
}
function runOnObject($o) {
$t = microtime(true);
for ($i=0; $i<100000; $i++) {
$prop = "prop{$i}";
$o->$prop = $i;
}
echo "".(microtime(true) - $t)." second ";
}
echo runOnObject(new Test()). "(With out __set)<p>";
echo runOnObject(new Test2()). "(With __set)";
结果: 0.084139823913574秒(没有__set) 0.47258400917053秒(带__set)
答案 0 :(得分:0)
如果添加__get,则可以将属性存储在私有数据结构(例如数组)中,允许直接访问类中的数据,同时仍保持相同的公共接口。
像这样:
class Container
{
private $properties = array();
public function __set($key, $value)
{
$this->doSomethingExpensive();
$this->properties[$key] = $value;
}
public function __get($key)
{
if (!isset($this->properties[$key])) {
throw new Exception('Invalid Property ' . $key);
}
return $this->properties[$key];
}
public function loadData($data)
{
$this->doSomethingExpensive();
foreach ($data as $key => $value) {
$this->properties[$key] = $value;
}
}
private function doSomethingExpensive()
{
echo 'Doing Work...' . PHP_EOL;
}
}
// Example
$c = new Container();
$c->loadData(array(
'alpha' => 'A',
'beta' => 'D',
'charlie' => 'C',
'delta' => 'D'
));
var_dump($c->alpha, $c->beta);
如果这会更快,我不知道,这取决于您的具体用例,因为您避免重复运行“昂贵”代码,但使用__get会有一些开销。
答案 1 :(得分:0)
显然不完全是您想要的,但另一个想法是...使用ArrayAccess
代替__set
动态集功能。虽然你必须更新'吨'的客户代码(不确定可能有多么不切实际)。
<?php
class A implements ArrayAccess
{
private $_doThings = false;
public function __construct() {
$this->loadData();
}
public function offsetExists($k) { return isset($this->$k); }
public function offsetGet($k) { return $this->$k; }
public function offsetUnset($k) { unset($this->$k); }
public function offsetSet($k, $v) {
if($this->_doThings)
$this->doSomeThingNecessaryBeforeSetAnything();
$this->$k = $v;
}
private function doSomeThingNecessaryBeforeSetAnything() {
echo __METHOD__ . PHP_EOL;
}
private function loadData() {
$this->doSomeThingNecessaryBeforeSetAnything();
$this->_doThings = false;
foreach (array('a' => 1, 'b' => 2, 'c' => 3) as $key=>$value) {
$this->$key = $value;
}
}
}
演示代码
$a = new A();
// Need to change all calls like $a->c = 4 to $a['c'] = 4
$a['c'] = 4;
var_dump($a);
因此需要进行痛苦的代码更改,但您可以获得两全其美的效果。动态行为和表现。