Путаница в PHP-сессии - PullRequest
3 голосов
/ 24 июня 2009

Хорошо, я чертовски запутался. У меня есть объект, который я храню в сеансе. Я могу добавить предметы к этому объекту. Довольно просто пока. Я инициализирую объект так:

$template = new Template($mysqli);
$_SESSION['template'] = serialize($template);

Теперь это должно создать совершенно новый объект и назначить его сеансу. Затем у меня есть код, который добавляет элементы через запрос AJAX. Этот код выглядит следующим образом:

$template = unserialize($_SESSION['template']);
$prodid = $_GET['product_id'];
$template->addItem($prodid);
echo var_dump($template->getItems());
$_SESSION['template'] = serialize($template);

Опять должно быть просто. Теперь проблема в том, что первый бит кода не сбрасывает $_SESSION['template'], хотя должен, поэтому я получаю все элементы, которые я добавил до сих пор, перезагрузка страницы не исправляет.

Я нашел файл, который причиняет вред, но я не знаю, что я могу сделать с этим. Это включение, и оно требуется для работы различных частей сайта. Я добавляю функциональность на сайт, я не думаю, что владельцы будут рады, если я удалю функциональность. Вот файл:

<?php

include_once( 'DBE.class.php' ) ;

################################################
# Function: Sessions_open
# Parameters: $path (string), $name (string)
# Returns: bool
# Description: This is an over-ride function call
#       that we need to create so that the php internal
#       session manager doesn't store our session in the
#       file system, since we are storing it in the
#       db. Storing a session in a file system on the
#       server inhibits scalability for two reasons:
#       1: A large number of users may be hitting the site
#           and clog the space on the hard-drive of the server
#           due to the sheer amount of session files stored
#       2: The website may be behind a load-balancer and
#           therefore the server handling the page request
#           may not have the session stored on its file system
################################################
function Sessions_open ( $path, $name ) {
    return TRUE ;
}


################################################
# Function: Sessions_close
# Parameters: N/A
# Returns: bool
# Description: This is an over-ride function call
#       that we need to create so that the php internal
#       session manager doesn't store our session in the
#       file system, since we are storing it in the
#       db. Storing a session in a file system on the
#       server inhibits scalability for two reasons:
#       1: A large number of users may be hitting the site
#           and clog the space on the hard-drive of the server
#           due to the sheer amount of session files stored
#       2: The website may be behind a load-balancer and
#           therefore the server handling the page request
#           may not have the session stored on its file system
################################################
function Sessions_close () {
    return TRUE ;
}


################################################
# Function: Sessions_read
# Parameters: $SessionID (string)
# Returns: (string) or (false) on error
# Description: This function is used at startup to read
#           the contents of the session. 
#           If no sess data, the empty string ("") is returned.
#           Otherwise, the serialized sess data is returned.
#           On error, false is returned.
################################################
function Sessions_read ( $SessionID ) {

    include_once( 'DBE.class.php' ) ;
    $dbe = new DBE() ;

    //default return value to false
    $returnVal = FALSE ;

    $query = "SELECT DataValue
                        FROM Sessions 
                        WHERE SessionID = '$SessionID' " ;

    $result = $dbe->Select( $query ) ;

    if( count( $result ) == 1 ) {
        $returnVal = $result[0]['DataValue'] ;

        //update the session so that we don't time-out after creating
        $query = "UPDATE Sessions
                            SET LastUpdated = NOW()
                            WHERE SessionID = '$SessionID'" ;
        $dbe->Update( $query ) ;

    } else {
        //Insert here to simplify the write function
        $query = "INSERT INTO Sessions (SessionID, DataValue) VALUES ( '$SessionID', '' )" ;

        $dbe->Insert( $query ) ;            //pass the insert stmt

        //set returnVal to '' being that we didn't find the SessionID
        $returnVal = '' ;
    }

    return( $returnVal ) ;
}

################################################
# Function: Sessions_write
# Parameters: $SessionID (string), $Data
# Returns: bool
# Description: This function is used at startup to read
#           the contents of the session. 
#           If no sess data, the empty string ("") is returned.
#           Otherwise, the serialized sess data is returned.
#           On error, false is returned.
################################################
function Sessions_write( $SessionID, $Data ) {

    include_once( 'DBE.class.php' ) ;
    $dbe = new DBE() ;

    //default to true
    $returnVal = TRUE ;

    //update the session
    $query = "UPDATE Sessions 
                            SET DataValue = '$Data'
                        WHERE SessionID = '$SessionID'" ;

    $result = $dbe->Update( $query ) ; //pass the update stmt to the dbEngine..

    //test for success
    if( $result == -1 )
        $returnVal = FALSE ;

    //return the return value
    return( $returnVal ) ;
}


################################################
# Function: Sessions_delete
# Parameters: $SessionID (string)
# Returns: bool
# Description: This function is used to delete the session
################################################
function Sessions_destroy( $SessionID ) {

    include_once( 'DBE.class.php' ) ;
    $dbe = new DBE() ;

    $query = "DELETE FROM Sessions WHERE SessionID = '$SessionID' " ;

    $dbe->Delete( $query ) ;

    return( TRUE ) ;
}

################################################
# Function: Sessions_delete
# Parameters: $SessionID (string)
# Returns: bool
# Description: This function is used to delete the session
################################################
function Sessions_gc( $aMaxLifetime ) {

    include_once( 'DBE.class.php' ) ;
    $dbe = new DBE() ;

    $query = "DELETE FROM Sessions WHERE (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP( LastUpdated )) > $aMaxLifetime " ;

    $dbe->Delete( $query ) ;

    return( TRUE ) ;
}

    session_set_save_handler( "Sessions_open", "Sessions_close",
                                 "Sessions_read", "Sessions_write",
                                 "Sessions_destroy", "Sessions_gc" ) ;

?>

Я думаю, что это меняет базовую функциональность сессий, но я не совсем уверен. И это вызывает у меня проблемы с сбросом шаблона в сеансе. У любого есть какие-либо идеи или знать, что я могу сделать, чтобы решить эту проблему. Я в полном недоумении, поэтому любая помощь очень ценится.

Ответы [ 4 ]

5 голосов
/ 24 июня 2009

Я не уверен, что это проблема, но вот что выскакивает, когда я читаю ваш код:

Ваш сериализованный объект использует соединение MySQL

$ template = new Template ($ mysqli);

в то время как ваш объект (возможно) может быть сериализован и не сериализован без проблем, соединение mysql не может, поэтому ваш несериализованный $ шаблон пытается работать с недопустимым дескриптором соединения / файла.

Вы можете попробовать повторно присоединить ваш несериализованный объект к действительному соединению базы данных.

Не зная, что находится внутри вашего класса Template (и какие ресурсы он использует и как), трудно догадаться, что не так, но я надеюсь, что это достаточно хорошая подсказка, с чего начать поиск.

Чтобы дать вам лучшее представление о том, о чем я говорю, подумайте:

template.php

<?php

class Template {
 function __construct($c) {
   $this->conn = $c;
   $this->foo = "bar";
 }
 function get_data() {
  $result = mysql_query("select 1234 as test", $this->conn);
  $data = mysql_fetch_array($result);
  return $data;
 }

 function attach_db($c) {
   $this->conn = $c;
 }
}

?>

first.php

<code><?php
session_start();
require('template.php');

$conn = mysql_connect('localhost', 'root', '');
$template = new Template($conn);
?>
<pre>

Your $template var, freshly created:
<?php var_dump($template); ?>

Accessing the resources:
<?php var_dump($template->get_data()); ?>

<?php
$_SESSION['template'] = serialize($template);
?>

other.php

<code><?php
session_start();
require('template.php');

$template = unserialize($_SESSION['template']);
?>
<pre>

Unserialized $template:
<?php var_dump($template); ?>
(notice that $template->foo === "bar" so your session un/serialization is working correctly)

Accessing the (now invalid) mysql resources:
<?php var_dump($template->get_data()); ?>

Если вы позвоните first.php, вы должны получить следующее:

Ваш $ template var, недавно созданный:
объект (шаблон) # 1 (2) {
[ "Подключ"] =>
ресурс (3) типа (ссылка на MySQL)
[ "Foo"] =>
строка (3) "бар"
}

Доступ к ресурсам:
массив (2) {
[0] =>
строка (4) "1234"
[ "Тест"] =>
строка (4) "1234"
}

При вызове others.php должно получиться:

Несериализованный $ шаблон:
объект (шаблон) # 1 (2) {
[ "Подключ"] =>
Int (0)
[ "Foo"] =>
строка (3) "бар"
}
(обратите внимание, что $ template-> foo === "bar", поэтому ваш сеанс un / serialization работает правильно)

Доступ к (теперь недействительным) ресурсам mysql:

Предупреждение: mysql_query (): указанный аргумент не является допустимым ресурсом MySQL-Link в файле template.php в строке 9

Предупреждение: mysql_fetch_array (): предоставленный аргумент не является допустимым ресурсом результата MySQL в файле template.php в строке 10

bool (false)

Чтобы решить эту проблему, вы можете воссоздать ресурсы, которые нельзя деактивировать / сериализовать.
Как это:

solution.php

<code><?php
session_start();
require('template.php');

$template = unserialize($_SESSION['template']);
?>
<pre>

Unserialized $template:
<?php var_dump($template); ?>

Attaching a valid db connection:
<?php
$conn = mysql_connect('localhost', 'root', '');
$template->attach_db($conn);
var_dump($template);
?>

Accessing the resources:
<?php var_dump($template->get_data()); ?>

Теперь вызов метода solution.php после вызова first.php должен дать вам следующее:

Несериализованный $ шаблон:
объект (шаблон) # 1 (2) {
[ "Подключ"] =>
Int (0)
[ "Foo"] =>
строка (3) "бар"
}

Присоединение действительного соединения БД:
объект (шаблон) # 1 (2) {
[ "Подключ"] =>
ресурс (3) типа (ссылка на MySQL)
[ "Foo"] =>
строка (3) "бар"
}

Доступ к ресурсам:
массив (2) {
[0] =>
строка (4) "1234"
[ "Тест"] =>
строка (4) "1234"
}

Как я уже сказал, не зная, что делает ваш шаблонный класс, невозможно точно сказать, что происходит ... это всего лишь одна возможность;)

Удачи!

1 голос
/ 24 июня 2009

Похоже, что они переопределяют стандартный обработчик сеанса для хранения данных сеанса в БД.

Загляните в таблицу Sessions и проверьте, правильно ли хранится ваш сериализованный объект.

0 голосов
/ 24 июня 2009

Возможно, ваш AJAX-вызов не содержит данных cookie сеанса и записывается в другой сеанс.

Можете ли вы использовать Fiddler и определить точный отправляемый запрос?

0 голосов
/ 24 июня 2009

Ну, вы должны быть в состоянии проверить базу данных, чтобы увидеть, как хранятся ваши данные (если вообще). Это, конечно, где я бы начал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...