【发布时间】:2011-10-22 14:45:11
【问题描述】:
我正在开发一个简单的 PHP 框架作为学习项目。我有一个请求对象,其方法名为_execute()。在该方法中,我(除其他外)创建了一个名为 pageController 的对象,对其调用方法,然后使用以下代码删除该对象:
$controller = new $this->_controllerName($this);
call_user_func(array($controller, $this->_methodName));
unset($controller);
如您所见,我将当前对象传递给新 pageController 的构造函数。我的构造函数如下:
public function __construct(Request $request) {
parent::__construct($request);
// More stuff
}
父母的控制器是这样的:
public function __construct(Request $request) {
$this->_request = $request;
}
这一切都很好,但是我的析构函数有问题。在 pageController 中,我还有另外两种方法:
public function __destruct() {
$this->_render();
}
public function _render($templateName = 'default') {
$this->_request->_response->_body = $this->_template->_render();
}
如果我从 pageController 的另一个方法中调用我的 _render() 方法,它的效果很好:然后我可以使用 $this->_response->_body 从初始请求对象中获取响应正文。但是,当我从析构函数中调用 _render() 方法时,请求对象中的更改不会更改。当我在调用_render() 之后立即调用print_r() 时,更改是 以某种方式可见...
总结:我对析构函数中的_request 属性所做的任何更改都不会在初始请求对象中发生更改,该对象引用相同,因为对象(几乎)总是不被复制但参考。我做错了什么?
注意:我在here 之前问过一个类似的问题,但这个问题不够具体(因为我当时并没有完全理解这个问题,并且由于我自己的一些不好的测试)。我想我应该问一个新的、具体的、直接的问题,以便有人可以帮助我。
【问题讨论】:
-
我认为您不应该将这种逻辑放入析构函数中。析构函数应该用来销毁东西并清理你的对象(数据库连接、套接字等)。如果您想取消设置对象,因为您想取消设置它(而不是渲染)怎么办?此外,
$this->_request->_response->_body大大违反了Law of Demeter。虽然您不必(有时只是不能)100% 遵守该原则,但通常最好缩短这些原则(例如:$this->_request->setResponseBody($body))以方便测试和调试。 -
如果你想学习如何做好 OOP,我也建议你阅读 SOLID principles。
-
@netcoder:感谢 cmets!我仍然是 OOP 的新手,最近在编写我的小框架时学到了很多东西。我基本上在 Kohana 的响应类上启发了我自己的响应类,效果非常好(我认为)。我肯定会在以后的体育场中创建自定义设置器和获取器(我已经阅读它提供了更大的灵活性),但这只是一个基本测试(结果比我想象的要难一些)。明天我将阅读有关得墨忒耳定律和 SOLID 原则的内容,感谢您的链接!
-
@netcoder:顺便说一句,最初我的析构函数中没有这个逻辑。但是当控制器 必须 输出页面时,将它放在析构函数中不是可以吗?什么时候调用第一个控制器?此外,我只是尝试一下,想了解为什么它不起作用......
-
@Frog:这不是一个很大的禁忌,但它没有多大意义(无论如何对我来说)。请记住,在析构函数(或其中调用的任何方法)中抛出的异常将导致致命错误,没有回溯、行号或文件名(在第 0 行的 Unknown 中抛出没有堆栈帧的异常)。这很难调试。出于这个原因,我避免将花哨的逻辑放在析构函数中。
标签: php oop destructor