实例化对象上的Magic Method __set()

时间:2010-04-14 20:10:57

标签: php design-patterns object reflection

好的,我有一个问题,对不起,如果我无法解释清楚,但代码说自己。

我有一个从给定的类名生成对象的类; 假设我们说这个类是模块:

public function name($name)
{

   $this->includeModule($name);

   try
   {
       $module    = new ReflectionClass($name);
     $instance = $module->isInstantiable() ? $module->newInstance() : "Err";

      $this->addDelegate($instance);
   }

   catch(Exception $e)
   {
      Modules::Name("Logger")->log($e->getMessage());
   }
   return $this;
 }

AddDelegate方法:

protected function addDelegate($delegate)
{
    $this->aDelegates[] = $delegate;
}

__call方法

public function __call($methodName, $parameters)
{

   $delegated = false;

   foreach ($this->aDelegates as $delegate)
   {
          if(class_exists(get_class($delegate)))
          {

         if(method_exists($delegate,$methodName))
         {
        $method     = new ReflectionMethod(get_class($delegate), $methodName);

        $function   = array($delegate, $methodName);

       return  call_user_func_array($function, $parameters);
          }
     }

   }

__get方法

public function __get($property)
    {
        foreach($this->aDelegates as $delegate)
        {
            if ($delegate->$property !== false)
            {
                return $delegate->$property;
            }

        }


    }

所有这一切都很好,期待函数__set

public function __set($property,$value)
    {

        //print_r($this->aDelegates);

        foreach($this->aDelegates as $k=>$delegate)
        {
            //print_r($k);
            //print_r($delegate);
            if (property_exists($delegate, $property))
            {
                $delegate->$property = $value;
            }

        }
        //$this->addDelegate($delegate);
        print_r($this->aDelegates);


    }

class tester
{
  public function __set($name,$value)
    {
        self::$module->name(self::$name)->__set($name,$value);
    }
}


Module::test("logger")->log("test"); //  this logs,  it works
echo Module::test("logger")->path; //prints /home/bla/test/ this is also correct

但是我不能像这样设置类日志的任何值

Module::tester("logger")->path ="/home/bla/test/log/";

类logger的path属性是公共的,因此它不是受保护或私有属性访问的问题。

我该如何解决这个问题?我希望我能清楚地解释我的问题。

编辑: 一个简单的演示

Modules::Name("XML_Helper")->xmlVersion ="Hello"; // default is 333
$a =  Modules::Name("XML_Helper")->xmlVersion; // now $a should contain "Hello" 
echo $a; // prints 333

我需要的是

Modules::Name("XML_Helper")->xmlVersion ="Hello"; // default is 333
$a =  Modules::Name("XML_Helper")->xmlVersion; // now $a should contain "Hello" 
echo $a; // prints Hello

2 个答案:

答案 0 :(得分:1)

  

类logger的path属性是公共的,所以它不是问题   受保护或私人财产访问。

那是你的问题。来自the docs

__set() is run when writing data to inaccessible properties.

这表明不会为公共属性调用__set()

答案 1 :(得分:1)

我意识到你已经说道路公开,但仍然值得一提:如果你使用的是PHP 5.3.0+,请注意property_exists()的这个怪癖:

  

5.3.0 |此函数检查是否存在独立于的属性   可访问性

换句话说,如果您选中if (property_exists($delegate, $property)),则无法保证您可以$delegate->$property访问if (property_exists($delegate, $property))进行写入(或阅读,但是 尝试写)。

至于实际故障排除:您可以尝试检查您的$property语句是否实际执行。如果没有,请检查{{1}}的{​​{3}}。

旁注:阅读你发布的代码相当困难,这使得排除故障有点痛苦。你能编辑你的帖子并正确地缩进吗?