PHP __get magic方法意外行为

时间:2013-08-10 11:26:58

标签: php

我有以下课程。

class Book {

    protected $name;
    protected $cost;
    protected $description;

    public function __construct(){
        $this->name = 'The X';
        $this->cost = 19.95;
        $this->description = 'Something about X';
    }

    public function __get($variable){
        return $this->$variable;
    }
}

class ReaderAbstract {

    protected $_book;

    public function __construct(){
        if(null == $this->_book){
            $this->_book = new Book();
        }
    }

    public function __get($variable){
        $method = 'get'.ucwords($variable);
        if(method_exists($this, $method)){
            return $this->$method();
        }
        return $this->getBook()->__get($variable);
    }

    public function getBook(){
        return $this->_book;
    }

}

class Reader extends ReaderAbstract {

    public function getCost(){
        return round($this->cost, 2);
        //return round($this->getBook()->cost, 2); Doing this works as expected
    }

}

现在,如果我这样做。

$reader = new Reader();
echo $reader->name; //This should work
echo '<br />';
echo $reader->cost; //This should go into an infinite loop
echo '<br />';
echo $reader->description; //This should work

上面的代码工作正常,期望语句echo $reader->cost;抛出"Undefined property: Reader::$cost"错误。

我的问题是:

  1. 为什么我无法访问该属性$cost

  2. 对$ cost属性的调用是否应该触发无限循环?即每当我调用$ reader-&gt;成本时,调用会被重定向到getCost()方法并且在getCost()方法内部如果我调用$ this-&gt; cost不应该调用方法getCost()创建无限循环吗?

  3. 感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

问题是__get方法不可重入,因此当您访问$reader->cost时,系统会首次调用它,然后调用Reader::getCost(),然后调用$this->cost强制PHP对__get进行递归调用,否则将被拒绝。

我不知道这是一个错误还是一个功能。阅读this page from the PHP manual并搜索“recursi”以便进一步阅读。