在OpenCart中混淆类和方法调用

时间:2013-04-16 07:53:58

标签: php opencart magic-methods

我有一个框架(OpenCart)Controller类(如: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();
而不是     $这 - >响应 - > setOutput();

我还提供了Controller课程的片段,以便您有所了解。

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
}

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

感谢。

2 个答案:

答案 0 :(得分:1)

使用魔术方法 __get()__set()非常容易。

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

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

是的,您可以改为编写$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()方法 - 但这仍然是更清晰/干净的解决方案。)

答案 1 :(得分:0)

这种魔法称为“超载” 这是一个较小的演示:

<?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。它解释得很清楚。