2013-04-16 23 views
5

Tôi có một khuôn khổ (OpenCart) lớp điều khiển (như: Danh mục/điều khiển/sản phẩm/product.php) mã trông giống như:lớp khó hiểu và gọi phương thức trong OpenCart

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

có một biểu hiện như $this->response->setOutput($this->render()); . Tôi biết những gì biểu thức này được sử dụng cho, nhưng tôi khá bối rối trong cách thức hoạt động.

$this là lớp hiện tại tức là ControllerProductProduct, có nghĩa là $this->response đối tượng phải tồn tại trong ControllerProductProduct hoặc lớp cha mẹ Controller. Nhưng đây không phải là trường hợp. Đối tượng này thực sự tồn tại trong thuộc tính được bảo vệ của lớp cha ControllerController::registry->data['response']->setOutput(). Vì vậy, nó không nên nói như:

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

thay vì $ this-> response-> setOutput();

Tôi cũng đưa ra một đoạn gồm Controller lớp để bạn có thể có ý tưởng.

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 
} 

Tôi không biết biểu thức này hoạt động như thế nào? Bất kỳ ý tưởng làm thế nào điều này là có thể?

Cảm ơn.

+0

Tôi có cùng một vấn đề với ngoại lệ không có phương thức __get được khai báo và nó cũng có thể được sử dụng, xem: http: //stackoverflow.com/questions/23183327/dynamically-adding-new-properties-in- php – user3505400

Trả lời

1

Điều này hoạt động rất dễ dàng bằng cách sử dụng các phương pháp ma thuật __get()__set().

Nếu bạn đang cố gắng để có được một biến lớp không thể tiếp cận (ví dụ như không được khai báo) một phương pháp ma thuật __get('property_name') được gọi.

Vì vậy, khi bạn đang cố truy xuất $response, phương pháp ma thuật __get() được gọi và $this->registry->get('response') được trả lại thay vì (không có $response thuộc tính được khai báo).

Có, bạn có thể viết $this->registry->get('response')->setOutput($this->render()); thay vào đó, nhưng điều này sẽ không được sử dụng nhiều và viết nhiều hơn. Nó là OK để cho PHP lấy biến bằng cách sử dụng phương thức __get() của nó, mặc dù nó không phải là quá sạch sẽ.

Dù sao, không có gì sai với giải pháp.

EDIT: một chút giải pháp chút sạch sẽ này:

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

Sau đó, Bạn có thể gọi một phương thức cụ thể trong mã của bạn và nó sẽ được rõ ràng đủ:

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

Nhưng điều này có nghĩa rằng cần có phương pháp getXYZ cho mỗi thuộc tính có thể trong khi __get() cho phép bạn mở rộng $registry mà không cần thêm công việc nào nữa (trong trường hợp tôi mô tả nếu Bạn sẽ thêm một thuộc tính khác vào $register Bạn sẽ phải thêm một phương thức getProperty() khác - nhưng vẫn là giải pháp rõ ràng/sạch hơn này).

0

Phép thuật này được gọi là "quá tải".
Dưới đây là bản demo nhỏ:

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

Nhìn vào http://php.net/manual/en/language.oop5.overloading.php. Nó được giải thích rõ ràng đủ.