使用__set和__get魔术方法来实例化类

时间:2012-04-19 20:42:52

标签: php

我正在自动加载我的类,并想要一种在使用时动态实例化该类的方法。

我希望在调用类时实例化一个类,而不是在我的父类中有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()上发现,而不会收到错误;

3 个答案:

答案 0 :(得分: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};
}

答案 1 :(得分:3)

__get需要返回一个值。就这样:

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

是这个难题的一部分。

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

如@KingCrunch所示,您可以将命名空间类引用为:

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

答案 2 :(得分: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();        
}

它负责了类名,并且实际进行了分配(代码中缺少了分配)。