2012-04-19 34 views
3

我自动加载我的类,并希望在使用时动态实例化类。使用__set和__get魔术方法实例化类

而不是在我的父类中有20个类实例化,我想要一个方法来实例化一个类时被调用。

例如:

$this->template->render(); 

将实例

$this->template = new Template(); 

我尝试这个

public function __set($name, $value) 
{ 
    return $this->$name; 
} 

public function __get($name) 
{ 
    $this->$name = new $name(); 
} 

这似乎并不工作,但我也觉得我这样做错误。

我弄不清楚的一个问题是我的类位于\ System命名空间中。我似乎无法解决new "\System".$name()new \System.$name()而没有出现错误;

回答

4
private $_template; 
public function __set($name, $value) 
{ 
    $this->{'_' . $name} = $value; 
} 

public function __get($name) 
{ 
    if (!$this->{'_' . $name}) { 
    $classname = '\\System\\' . ucfirst($name); 
    $this->{'_' . $name} = new $classname(); 
    } 
    return $this->{'_' . $name}; 
} 
+0

是有办法不多自动创建属性如何,您可以在__construct()方法创建一个属性? – Eli 2012-04-19 21:01:22

+0

你已经想要命名你的“虚拟”属性'template',因此命名真正的属性并不明智。 – KingCrunch 2012-04-19 21:02:31

+1

不应该'__set()'方法设置一些东西而不是返回一些东西? – 2012-04-19 21:11:59

1

你可能期待更多这样的:

public function __set($name, $value) 
{ 
    $this->$name = $value; 
} 

public function __get($name) 
{ 
    if (isset($this->$name)) { 
     return $this->$name; 
    } 

    $class = sprintf('\\System%s', ucfirst($name)); 
    return $this->$name = new $class();   
} 

它需要的类名的,而且转让实际上是由保健(这是在你的代码丢失)。

3

__get需要返回一个值。因此:

public function __get($name) 
{ 
    $this->$name = new $name(); 
    return $this->$name; 
} 

是拼图的一部分。

根据你所说的,你根本不需要__set - 除非等价属性被声明为受保护,并且你将从实例外部设置它(但为什么要这么做)。

正如@KingCrunch表示,你可以参考一个命名空间类为:

$classname = '\\System\\' . ucfirst($name); 
$foo = new $classname; 
+0

+1 @ AD7six OOP的最佳特性..和国会10K – liyakat 2013-07-11 08:00:35

相关问题