5

我有一个框架(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中。但这种情况并非如此。这个对象实际上存在于父类的受保护属性ControllerController::registry->data['response']->setOutput()。所以不应该这样说:

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

而不是 $this->response->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
}

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

谢谢。

4

2 回答 2

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不需要进一步工作的情况下扩展这将是更清晰/干净的解决方案)。$registergetProperty()

于 2013-04-16T08:26:16.390 回答
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。解释得够清楚了。

于 2013-04-16T08:17:13.110 回答