2011-02-24 41 views
2

我注意到使用__destruct在PHP 5.3編寫使用Zend_Session_Namespace數據略有些意外的行爲寫的Zend_Session_Namespace:在自毀

public function __destruct(){ 
    $this->getSession()->data = $this->data; 
} 
// .... 
private function getSession() 
{ 
    if (! self::$zendSession) { 
     // this next line is fine because the object is a singleton 
     self::$zendSession = new Zend_Session_Namespace(self::SESSION_NAMESPACE); 
    } 
    return(self::$zendSession); 
} 

析構函數獲取調用,但數據沒有得到寫入。但是,如果我在對象完成所有必要的操作並在腳本終止之前強制銷燬之後隱式地調用了破壞,則數據寫入正常,但我寧願不這樣做。

我想它與這個錯誤有關:http://bugs.php.net/29032(對我來說,這個錯誤似乎有點老),並且在它的表面上,修復看起來不錯(註冊__destruct作爲關閉功能,這在$_SESSION之前調用是不可用的),但不會析構函數被調用兩次(一次通過register_shutdown_function和一次自動?

當然寫對象數據的奇數位關閉會話是一件已經解決的事情?人們做什麼當這是必需的?

(OSX 10.6.6,Apache 2.2.15(Unix),PHP 5.3.3,Zend Framework 1.7.2)

+0

還有一些涉及'zend_controller_action - > _ redirect()'的複雜問題,但我不想讓帖子太難理解。基本上,我注意到如果有一連串的請求,使用'zend_controller_action - > _ redirect()'轉發到下一個會導致析構函數退出它引用'Zend_Session_Namespace'的行。對於鏈中的最後一個請求(其中'zend_controller_action - > _ redirect()'是* not *調用,析構函數正常完成,並且數據寫入會話 – sennett 2011-02-24 09:30:03

回答

2

這是一個雞和雞蛋的問題。如果會話終止被留下直到所有對象被銷燬,那麼將不可能爲會話保存處理程序使用對象。

register_shutdown_function解決方法很好。爲避免運行代碼兩次,您應將會話終止代碼移入您註冊的其他功能。在一個仍然存在的對象上手動調用__destruct()看起來有點難看;)

+0

非常感謝,我將註冊一個函數(而不是__destruct ),它將會話數據寫入關閉函數,我得到了關於雞和蛋的說法,我嘗試實例化一個新的Zend_Session_Namespace對象,而不是從類變量中拉出實例,我想這會導致析構函數被調用在稍後的關機程序中?這沒有什麼區別,所以我想這個行爲源自$ _SESSION本身。感謝您的幫助 - 會投票但沒有足夠的代表:) – sennett 2011-02-24 10:13:39

+0

不幸的是,關機功能也是如此。我認爲用這種方式使用析構函數的問題不大(因爲如上所述,當新請求未啓動時,它工作正常),更多的是重定向問題,以及Zend啓動新的HTTP請求的方式,以及PHP處理它的方式(目前正在研究 - http://www.php.net/manual/en/features.connection-handling.php)。這意味着,雖然答案是正確的,但我提出了錯誤的問題! – sennett 2011-02-24 10:49:02

+0

@sennett action - > _ redirect()使用[Redirector helper](http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Controller/Action/Helper/Redirector.php),其默認值首先關閉會議。你可以在助手上調用'setCloseSessionOnExit(false)'來防止這種情況。 – 2011-02-24 10:55:15