Сессии PHP и unserialize()

Vladimir
Опубликовано в: PHP

Как прочитать данные из сохранённой сессии

Иногда случаются ситуации, когда сессии приходится хранить в базе данных и, что еще хуже, иногда приходится читать данные из сериализованной сессии.
Начнём с того, что сессии в PHP сохраняются не с помощью serialize(). Точнее, у сохранённой сессии несколько другой формат, так как PHP приходится хранить еще и имя переменной.

В общем виде это выглядит так:
name|value;name|value

Например:
a|i:1;b|i:2;
“транслируется” в

[-]
View Code PHP
    $_SESSION['a'] = 1;
    $_SESSION['b'] = 2;

И вот, иногда случается, что необходимо извлечь данные из сохранённой сессии. Соблазн использовать unserialize() достаточно велик, так как в этом случае не придётся изобретать велосипед заново и писать код, выполняющий ту же самую функцию.
На php.net (и других сайтах) я неоднократно встречал код, предназначенный для для разбора сессий. Но что удивительно, все авторы просто разбивают строку по символу ‘|’: слева — имя переменной, справа  — её сериализованное значение. Но что меня удивляет: никто из авторов не подумал, что строковые данные тоже могут содержать вертикальную черту! Да, вероятность этого, признаю, небольшая, но последствия могут быть не очень хорошими :-)

Года два назад я написал функцию, которая разбирает сессию. Хотя код не очень удачный (смесь автоматной модели с хардкодингом), сбоев еще не было.

[-]
View Code PHP
    function unserialize_session($s)
    {
        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;
    }
Добавить в закладки
  • del.ici.ous
  • Digg
  • Furl
  • Google
  • Simpy
  • Spurl
  • Y! MyWeb
  • БобрДобр
  • Мистер Вонг
  • Yandex.Закладки
  • Текст 2.0
  • News2
  • AddScoop
  • RuSpace
  • RUmarkz
  • Memori
  • Google Bookmarks
  • Писали
  • СМИ 2
  • Моё Место
  • 100 Закладок
  • Ваау!
  • Technorati
  • RuCity
  • LinkStore
  • NewsLand
  • Lopas
  • Закладки - IN.UA
  • Connotea
  • Bibsonomy
  • Trucking Bookmarks
  • Communizm
  • UCA
  • Slashdot
  • Magnolia
  • Blogmarks
  • Current
  • Meneame
  • Oknotizie
  • Diigo
  • Funp
  • Hugg
  • Dealspl.us
  • N4G
  • Mister Wong
  • Faves
  • Yigg
  • Fresqui
  • Care2
  • Kirtsy
  • Sphinn
  • SaveThis.ru

Связанные записи

6
Март
2008

Комментарии к статье «Сессии PHP и unserialize()» (3)  »

  1. [...] как прочитать данные из Session::session_data, можно прочитать в этой статье. Сразу отмечу, что PHP самостоятельно выполняет [...]

  2. Зануда says:

    А если так?

    [-]
    View Code PHP
    <?php
      $string = "foo|bar|baz|10001010101";
      print_r(explode('|', $string, 2));
    ?>
  3. Vladimir says:

    Зануда, Ваш вариант будет работать только в том случае, если заранее известно количество элементов в $_SESSION, а также то, что вертикальная черта может быть только в последнем элементе.

    Если взять Ваш пример:

    [-]
    View Code PHP
    $data[0] = 'foo';
    $data[1] = 'bar|baz|10001010101';

    Но не

    [-]
    View Code PHP
    $data[0] = 'foo|bar';
    $data[1] = 'baz|10001010101';

Подписаться на RSS-ленту комментариев к статье «Сессии PHP и unserialize()» Trackback URL: http://blog.sjinks.org.ua/php/6-php-sessions-unserialize/trackback/

Оставить комментарий к записи «Сессии PHP и unserialize()»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя