session_handler отключает поле данных сеанса от прежнего

#php #session

#php #сеанс

Вопрос:

Я запустил тот же сеанс в DB и отлично работает, чтобы пользователь входил в систему дольше, чем время по умолчанию из php.ini.

Я понял две вещи, и я пока не мог это исправить

Сбор мусора не работает с функцией session_handler

И если я использую эту функцию unset ($_session[«var»]), поле данных по-прежнему содержит имя переменной сеанса и то же значение.

Мой вопрос:

Как я могу удалить значение из поля данных?

Как исправить сборку мусора, чтобы удалить строку через 30 минут? (поскольку это не удаление)

это мой код session_handler:

 CREATE TABLE IF NOT EXISTS `sessions` (
  `session_id` char(32) NOT NULL,
  `last_update` datetime DEFAULT NULL,
  `session_data` longtext,
  PRIMARY KEY (`session_id`)
)

$sdbc = NULL;

/*** Open Session ***/
function _Session_Open()
{
    global $sdbc;

    $db = 'dataBase';
    $us = 'user';
    $pw = 'password';

    // Connect to the database.
    $sdbc = mysqli_connect('host',$us, $pw, $db) or die ('Error: ' . mysqli_error());

    return true;

} // end of _Session_Open    


/*** Close Session ***/
function _Session_Close()
{
    global $sdbc;

    return mysqli_close($sdbc);

} // end of _Session_Close


/*** Read Session ***/
function _Session_Read($sid)
{
    global $sdbc;

    $now = date("Y-m-d H:i:s"); 

    $sid = mysqli_real_escape_string($sdbc, $sid);

    $sql = " SELECT session_data FROM sessions WHERE session_id = '$sid' ";

    $row = mysqli_query($sdbc, $sql) or die ('Line 49 ' .mysqli_error());

    // Retrieve the results:
    if (mysqli_num_rows($row) == 1) 
    {

        list($data) = mysqli_fetch_array($row, MYSQLI_NUM);

        // Return the data:
        return $data;

    } else { // Return an empty string.
        return '';
    }

    /*** clear variables ***/ 
    unset($now, $sid, $sql, $row, $data);   

} // end of _Session_Read


/*** Write Session ***/
function _Session_Write($sid, $sdata)
{
    global $sdbc;

    $now = date("Y-m-d H:i:s");

    $sid   = mysqli_real_escape_string($sdbc, $sid);
    $sdata = mysqli_real_escape_string($sdbc, $sdata);

    $sql = " REPLACE INTO sessions 
             (session_id, last_update, session_data)
             VALUES 
             ('$sid', '$now','$sdata')
            ";

    $row = mysqli_query($sdbc, $sql) or die ('Line 86 ' .mysqli_error());

    return mysqli_affected_rows($sdbc);

    /*** clear variables ***/ 
    unset($now, $sid, $sql, $row, $data);   

} // end of _Session_Write


/*** Destroy Session ***/
function _Session_Destroy($sid)
{

    global $sdbc;

    $sql  = "DELETE FROM sessions WHERE session_id = '$sid'";

    $row = mysqli_query($sdbc, $sql) or die ('Line 104 ' .mysqli_error());

    return mysqli_affected_rows($sdbc);

    /*** clear variables ***/ 
    unset($sid, $sql, $row);    

} // end of _Session_Destroy



/*** Garbagge Collector ***/
function _Session_GC($maxlifetime)
{
    global $sdbc;

    $yesterday = date("Y-m-d H:i:s", time() - 60*270);

    $sql  = "DELETE FROM sessions WHERE last_update < '$yesterday' ";

    $row = mysqli_query($sdbc, $sql) or die ('Line 124 ' .mysqli_error());

    return mysqli_affected_rows($sdbc);

    /*** clear variables ***/ 
    unset($yesterday, $sql, $row);  

} 


    /* Register the session handling functions with PHP. */
    session_set_save_handler(
                             '_Session_Open',
                             '_Session_Close',
                             '_Session_Read',
                             '_Session_Write',
                             '_Session_Destroy',
                             '_Session_GC'
                         );

    session_start();
  

Комментарии:

1. Просто примечание: вместо ‘Line 86’, ‘Line 104’ и т.д., Вас может заинтересовать __LINE__ константа PHP.

2. Спасибо, мудрец, я воспользовался твоим предложением.

Ответ №1:

У вас есть несколько вызовов unset() после возврата из функций.

Примеры:

 if (mysqli_num_rows($row) == 1) 
{
    list($data) = mysqli_fetch_array($row, MYSQLI_NUM);
    // Return the data:
    return $data;
} else { // Return an empty string.
    return '';
}

// WON'T REACH THIS CODE

/*** clear variables ***/ 
unset($now, $sid, $sql, $row, $data);
  

и

 return mysqli_affected_rows($sdbc);

/*** clear variables ***/ 
unset($now, $sid, $sql, $row, $data);
  

Исправить:

 $result = ... ;
unset ( ... );
return $result;
  

Комментарии:

1. Я понял, спасибо, Jcinacio, я исправил эту часть. Но у меня все еще есть проблема с отключением сеанса. Имя и значение не были удалены из поля данных в базе данных.

2. Из комментариев в руководстве по session_set_save_handler, я считаю, что вам нужно явно вызвать register_shutdown_function('session_write_close');

Ответ №2:

Я решил одну проблему

Я вызывал session_write_close(); каждый раз, когда я читал, добавлял или изменял значения переменных сеанса.

итак, теперь я вызываю session_write_close (); один раз в конце моего скрипта и работает идеально.

Но я не смог разрешить сборку мусора, чтобы удалить строку через 30 минут.