【问题标题】:Modifications in object __destruct() not saved PHP [duplicate]对象 __destruct() 中的修改未保存 PHP [重复]
【发布时间】:2011-10-22 14:45:11
【问题描述】:

可能重复:
Pass reference to $this in constructor PHP

我正在开发一个简单的 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


【解决方案1】:

您使用的是什么 PHP 版本?我无法使用以下代码在 5.3.6 上复制您的问题:

class Foo {
    public function __construct(Bar $bar) {
        $this->bar = $bar;
    }
    public function __destruct() {
        $this->bar->value = 'set by Foo::__destruct';
    }
}

class Bar {
    public function __construct() {
        $this->value = 'set by Bar::__construct';
    }
}

$bar = new Bar();
$foo = new Foo($bar);
print $bar->value . PHP_EOL;  // => 'set by Bar::__construct'
unset($foo);
print $bar->value . PHP_EOL;  // => 'set by Foo::__destruct'

这是否与您尝试做的事情相同。如果是...听起来您的应用程序逻辑的其他部分可能正在干扰。

【讨论】:

  • 感谢您的回答!这不完全是我所需要的,但我已经做了一个非常简单的版本,我需要的东西确实可以工作......所以你是对的,错误一定在我的逻辑中的某个地方。真的很奇怪,因为我已经做了一个简化版,我估计还不够简单……反正我现在必须找到错误。感谢您的宝贵时间!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-16
  • 2019-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多