這是事情。我的一位同事正在嘗試覆蓋我們使用的框架的會話處理。該框架默認使用PHP自己的本地會話處理,但他現在正試圖在請求之間實現數據庫層。下面是一個真正的挑戰:爲什麼PHP在會話寫入之前調用關閉函數?
問題在於數據庫對象在再次寫入會話時不可用,但它可用於其他功能,例如從會話讀取數據時。這是一個狂野的行爲。這就是我們所做的:
register_shutdown_function('exithandler');
session_set_save_handler(
'sess_open',
'sess_close',
'sess_read',
'sess_write',
'sess_destroy',
'sess_gc'
);
每這些功能也寫一行到我們的日誌文件,我們可以用函數的名稱跟蹤。無論何時調用該函數,都會執行此操作。現在這裏有兩個請求的URL,第一個是實際寫入會話的地方(會話的新數據),第二個是剛剛檢查會話數據(沒有寫入數據)。這是難題:
/login/
sess_open
sess_read
exithandler
sess_write
sess_close
/account/
sess_open
sess_read
sess_write
sess_close
exithandler
爲什麼這種行爲不同?爲什麼在數據存儲在會話中之前呼叫出口處理程序,爲什麼對於常規頁面來說同樣不是這樣,儘管實際上調用了相同的方法?
問題是在調用了exithandler之後,我們沒有任何類可用了,我假設PHP垃圾回收器已經在我們所有的類上調用了__destruct()方法,並且它們都消失了。這很糟糕。
任何人都知道爲什麼PHP的行爲是這樣嗎?
您使用的是哪個版本的PHP? –
我已經使用PHP 5.4測試過了,我只能重現這兩種請求類型的操作順序:讀取和寫入會話數據。 – nickb
某些PHP版本存在一個常見問題,需要您在調用'session_set_save_handler()'之前添加一行。首先使用這個:'register_shutdown_function('session_write_close')'看看是否能解決你的不穩定行爲。 –