我已經從PHP 5.6升級到7,並使用自定義會話處理程序腳本來管理數據庫中的會話,以便我可以更好地控制我的用戶。除了一件事之外,一切都很好。PHP 7 session_regenerate_id失敗和PDO調用成員函數prepare()null
session_regenerate_id(true);
用戶成功登錄後,爲避免會話固定,我們調用session_regenerate_id。使用PHP5.6工作得很好,而不是PHP7:
[14-May-2016 02:04:07 UTC] PHP Warning: Uncaught Error: Call to a member function prepare() on null in /home/xxxx/protected/class.database.php:38 Stack trace:
#0 /home/xxxx/protected/class.session.php(37): Database->query('SELECT data FRO...')
#1 [internal function]: Session->_read('kuq04akaagkjd5n...')
#2 /home/xxxx/protected/user_auth_fns.php(705): session_regenerate_id(true)
#3 /home/xxxx/public_html/passengersdir/login.php(42): login_user('xxxx', 'xxxx', 'xxxx', NULL)
#4 {main}
thrown in /home/xxxx/protected/class.database.php on line 38 [14-May-2016 02:04:07 UTC] Recoverable error: session_regenerate_id(): Failed to create(read) session ID: user (path:) in /home/xxxx/protected/user_auth_fns.php on line 705
顯然session_regenerate返回false,但PHP 5.6讓它滑動。這是PHP的官方迴應:
- PHP 7.0及更高版本不允許來自用戶保存處理程序的錯誤返回值。 用戶讀處理程序務必返回「字符串」數據總是成功。
- 本地保存處理程序必須返回SUCCESS以成功處理包括不存在的會話數據的情況。
FALSE
/失敗的意思是「讀取時出現錯誤」,如權限/網絡/等錯誤。
https://bugs.php.net/bug.php?id=71187
有些人找到了一個解決方法在這裏: https://github.com/magento/magento2/issues/2827
It appears to be an issue with the read function not always returning a string. As a temporary fix I cast the return value for the read() function in the SessionHandler as a string.
我不喜歡的解決方法。我可以簡單地刪除session_generate_id
,它的工作原理類似於過去的美好時光,但您可以開始進行會話固定。
理想情況下,我想解決這個問題,或找到一個更好的方式來成功登錄後打擊會話固定。感謝您的期待。
這裏是有問題的代碼:
public function __construct(){ // this is class.database.php
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try{
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
}
// Catch any errors
catch(PDOException $e){
$this->error = $e->getMessage();
}
}
public function query($query){
// this throws Uncaught Error: Call to a member function prepare() on null in /home/opentaxi/protected/class.database.php:38
$this->stmt = $this->dbh->prepare($query);
}
public function bind($param, $value, $type = null){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute(){
return $this->stmt->execute();
}
// this is from class.session.php
public function _read($id){
//this is /home/opentaxi/protected/class.session.php(37): Database->query('SELECT data FRO...')
$this->db->query('SELECT data FROM sessions WHERE id = :id');
$this->db->bind(':id', $id);
if($this->db->execute()){
$row = $this->db->single();
return (string)$row['data']; // I have the workaround that's not working!
}else{
return '';
}
}
***「這裏是有問題的代碼:」***我沒有看到它'session_generate_id'。 –