【问题标题】:Confusing class and method call in OpenCartOpenCart 中令人困惑的类和方法调用
【发布时间】:2013-04-16 18:32:35
【问题描述】:

我有一个框架(OpenCart)控制器类(如:catalog/controller/product/product.php)代码如下:

class ControllerProductProduct extends Controller {
    public function index() {
      //some code
      $this->response->setOutput($this->render());
      //some more code
    }
}

有一个像$this->response->setOutput($this->render()); 这样的表达式。我知道这个表达式的用途,但我对它的工作原理很困惑。

$this 指的是当前类,即ControllerProductProduct,这意味着$this->response 对象必须存在于ControllerProductProduct 或其父类Controller 中。但这种情况并非如此。该对象实际上存在于父类Controller 的受保护属性中,如Controller::registry->data['response']->setOutput()。所以不应该这样说:

$this->registry->data['response']->setOutput();

而不是 $this->response->setOutput();

我还提供了Controller 类的 sn-p,以便您有想法。

abstract class Controller {
    protected $registry;    
    //Other Properties
    public function __construct($registry) {
        $this->registry = $registry;
    }
    public function __get($key) {
        //get() returns registry->data[$key];
        return $this->registry->get($key);
    }
    public function __set($key, $value) {
        $this->registry->set($key, $value);
    }
    //Other methods
}

我不知道这个表达式是如何工作的?知道这怎么可能吗?

谢谢。

【问题讨论】:

标签: php opencart magic-methods


【解决方案1】:

使用 魔术方法 __get()__set() 很容易做到这一点。

如果您试图获取一个不可访问的类变量(例如未声明的),则会调用一个神奇的 __get('property_name') 方法。

因此,当您尝试检索 $response 时,会调用魔术方法 __get() 并返回 $this->registry->get('response')(因为没有声明 $response 属性)。

是的,您可以改写$this->registry->get('response')->setOutput($this->render());,但这并没有多大用处,需要更多的写作。让 PHP 使用它的__get() 方法检索变量是可以的,虽然它不是那么干净。

不管怎样,解决方法没有问题。

编辑:更清洁的解决方案是这样的:

class Controller {
    //...
    function getResponse() {
        return $this->registry->get('response');
    }
    //...
}

然后你可以在你的代码中调用一个具体的方法,这就足够清楚了:

class ControllerProductProduct extends Controller {
    public function index()
        //...
        $this->getResponse()->setOutput($this->render());
    }
}

但这意味着每个可能的属性都需要getXYZ 方法,而__get() 允许您扩展$registry 而无需进一步工作(在我描述的情况下,如果您要添加另一个$register 的属性您必须添加另一个 getProperty() 方法 - 但这仍然是更清晰/干净的解决方案。

【讨论】:

    【解决方案2】:

    这种魔法称为“重载”。
    这是较小的演示:

    <?php
    
    class PropsDemo 
    {
        private $registry = array();
    
        public function __set($key, $value) {
            $this->registry[$key] = $value;
        }
    
        public function __get($key) {
            return $this->registry[$key];
        }
    }
    
    $pd = new PropsDemo;
    $pd->a = 1;
    echo $pd->a;
    

    看看http://php.net/manual/en/language.oop5.overloading.php。解释的够清楚了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 2010-11-23
      相关资源
      最近更新 更多