Сессии PHP и unserialize()
Как прочитать данные из сохранённой сессии
Иногда случаются ситуации, когда сессии приходится хранить в базе данных и, что еще хуже, иногда приходится читать данные из сериализованной сессии.
Начнём с того, что сессии в PHP сохраняются не с помощью serialize(). Точнее, у сохранённой сессии несколько другой формат, так как PHP приходится хранить еще и имя переменной.
В общем виде это выглядит так:
a|i:1;b|i:2;
«транслируется» в
$_SESSION['b'] = 2;
И вот, иногда случается, что необходимо извлечь данные из сохранённой сессии. Соблазн использовать unserialize() достаточно велик, так как в этом случае не придётся изобретать велосипед заново и писать код, выполняющий ту же самую функцию.
На php.net (и других сайтах) я неоднократно встречал код, предназначенный для для разбора сессий. Но что удивительно, все авторы просто разбивают строку по символу ‘|’: слева — имя переменной, справа — её сериализованное значение. Но что меня удивляет: никто из авторов не подумал, что строковые данные тоже могут содержать вертикальную черту! Да, вероятность этого, признаю, небольшая, но последствия могут быть не очень хорошими
Года два назад я написал функцию, которая разбирает сессию. Хотя код не очень удачный (смесь автоматной модели с хардкодингом), сбоев еще не было.
{
static $tt = array(
/* 0 1 2 */
/* | */ array(3, 1, 1),
/* " */ array(1, 0, 1),
/* \ */ array(0, 2, 1),
/* (rest) */ array(0, 1, 1),
);
static $chars = '|"\\';
$result = array();
$len = strlen($s);
$name = '';
$state = 0;
$value = '';
$what = 'name';
for ($i=0; $i<$len; ++$i) {
$row = strpos($chars, $s[$i]);
if (false === $row) {
$row = 3;
}
$state = $tt[$row][$state];
if (3 == $state) {
if ('value' == $what) {
for ($j=strlen($value)-1; $j>0; --$j) {
if (';' == $value[$j] || '}' == $value[$j]) {
$result[$name] = substr($value, 0, $j+1);
$name = substr($value, $j+1);
$value = '';
break;
}
}
}
else {
$what = 'value';
}
$state = 0;
}
else {
$$what .= $s[$i];
}
}
if ('' != $name) {
$result[$name] = $value;
}
foreach ($result as $name => $value) {
$result[$name] = unserialize($value);
}
return $result;
}
Связанные записи
Автор: Vladimir; опубликовано в: PHP; метки: PHP, unserialize, сессияМарт
2008


Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.






[...] как прочитать данные из Session::session_data, можно прочитать в этой статье. Сразу отмечу, что PHP самостоятельно выполняет [...]
А если так?
$string = "foo|bar|baz|10001010101";
print_r(explode('|', $string, 2));
?>
Зануда, Ваш вариант будет работать только в том случае, если заранее известно количество элементов в
$_SESSION, а также то, что вертикальная черта может быть только в последнем элементе.Если взять Ваш пример:
$data[1] = 'bar|baz|10001010101';
Но не
$data[1] = 'baz|10001010101';
Спасибо, работает)