Confusing class and method call in OpenCart

瘦欲@ 提交于 2019-12-22 06:02:34

问题


I have a framework (OpenCart) Controller class (like: catalog/controller/product/product.php) the code looks like:

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

there is an expression like $this->response->setOutput($this->render());. I know what this expression is used for, but I am pretty confused in how it works.

$this refers to current class i.e. ControllerProductProduct, it means $this->response object must exist in either ControllerProductProduct or its parent class Controller. But this is not the case. This object actually exists in a protected property of parent class Controller as Controller::registry->data['response']->setOutput(). So shouldn't it say like:

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

instead of $this->response->setOutput();

I am also giving a snippet of Controller class so you can have idea.

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
}

I've no clue how this expression is working? Any idea how this is possible?

Thanks.


回答1:


This is working very easily using magic methods __get() and __set().

If You are trying to get an inaccessible class variable (e.g. that is not declared) a magic __get('property_name') method is invoked.

Thus when You are trying to retrieve $response, a magic method __get() is called and $this->registry->get('response') is returned instead (as there is no $response property declared).

Yes, You could write $this->registry->get('response')->setOutput($this->render()); instead, but this would be of not much use and more writing. It is OK to let the PHP retrieve the variable using it's __get() method, though it is not so clean.

Anyway, there is nothing wrong with the solution.

EDIT: a little bit cleaner solution would be this:

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

Then You could call a concrete method in Your code and it would be clear enough:

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

But this would mean that there would be a need of getXYZ method for each possible property while __get() allows You to extend the $registry with no further work needed (in the case I described if You would add another property to $register You would have to add another getProperty() method - but still this would be more clear/clean solution).




回答2:


This magic called "overloading".
Here it is smaller demo:

<?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;

Look at http://php.net/manual/en/language.oop5.overloading.php. It's explained clearly enough.



来源:https://stackoverflow.com/questions/16031589/confusing-class-and-method-call-in-opencart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!