2012-01-08 59 views
1

Chart类实际上允许我创建简单的属性(string型,boolean等等),以及嵌套object性能调用魔术__call方法是这样的:以最小的努力创建任意对象层次结构?

$chart = new Chart(); 
$chart->simple = 'Hello'; 
$chart->newComplex(); 

var_dump($chart); 

输出:

object(Chart)[1] 
    public 'simple' => string 'Hello' (length=5) 
    public 'complex' => 
    object(stdClass)[2] 

我想添加能力来创建嵌套object属性作为其他属性的子女(不是图表本身的子女)这样的:

$chart->newComplex2($chart->newComplex1()); 

问题是:如何使用$args参数和修改__call()做到这一点?

class Chart 
{ 

    public function __call($name, $args) 
    { 

     $type = substr($name, 0, 3); 
     $field = lcfirst(substr($name, strlen($type))); 

     switch($type) 
     { 
      case 'get': return isset($this->$field) ? $this->$field : null; 
      case 'new': return $this->$field = new stdClass(); 
     } 

    } 

} 
+0

作为一个建议,首先提供您正在寻找的功能并接受'$ args'数组或从'func_get_args'创建它的函数的非魔术函数代码。您稍后可以继续添加魔术界面。在你的代码示例中,'$ args [0]'是你想知道的第一个参数。 – hakre 2012-01-08 11:04:09

+1

您不应该混合协作者和创作者图。你的对象应该有单一的责任。允许他们创建对象是一项责任。将其分解为工厂和生成器模式。 – Gordon 2012-01-08 11:28:17

+0

@戈登感谢您的提示。该图表是一个简单的数据容器对象。实际数据(即图表系列)是在别处创建的,并在构建器(模式)类中与图表合并。所以我认为我们有单一的责任模式受到尊重。 – gremo 2012-01-08 11:47:08

回答

0

我自己找到解决方案。诀窍是将父项属性传递给__call。这里是代码:

public function __call($name, $args) 
{ 

    $type = substr($name, 0, 3); 
    $field = lcfirst(substr($name, strlen($type))); 

    switch($type) 
    { 
     case 'get': 
      return isset($this->$field) ? $this->$field : null; 
     case 'new': 
      return (isset($args[0]) ? $args[0]->$field = new stdClass() 
       : $this->$field = new stdClass()); 
     default: return $this->$name(); 
    } 

}