session_id
session_id() используется для получения или установки идентификатора текущей сессии.
Константа SID также может быть использована для получения текущего имени и идентификатора сессии в виде строки, подходящей для добавления в URL-адреса. Смотрите также Работа с сессиями.
Список параметров
Если указан параметр id и он не равен null , то он заменит идентификатор текущий сессии. Для этого session_id() следует вызывать до session_start() . В зависимости от обработчика сессии, не все символы возможно использовать в идентификаторе сессии. Например, файловый обработчик сессии поддерживает только символы из диапазона a-z A-Z 0-9 , (запятая) и — (минус) !
Замечание: При использовании сессионных cookie, указание id для session_id() приводит к тому, что при вызове session_start() всегда будут отправлены новые cookie, независимо от того, совпадает ли идентификатор текущей сессии с вновь установленным.
Возвращаемые значения
session_id() возвращает идентификатор текущей сессии или пустую строку ( «» ), если нет текущей сессии (идентификатор текущей сессии не существует). В случае неудачи возвращает false .
Список изменений
| Версия | Описание |
|---|---|
| 8.0.0 | id теперь может быть null . |
Смотрите также
- session_regenerate_id() — Генерирует и обновляет идентификатор текущей сессии
- session_start() — Стартует новую сессию, либо возобновляет существующую
- session_set_save_handler() — Устанавливает пользовательские обработчики хранения сессии
- session.save_handler
User Contributed Notes 21 notes
8 years ago
It may be good to note that PHP does not allow arbitrary session ids. The session id validation in PHP source is defined in ext/session/session.c in the function php_session_valid_key:
To put it short, a valid session id may consists of digits, letters A to Z (both upper and lower case), comma and dash. Described as a character class, it would be [-,a-zA-Z0-9]. A valid session id may have the length between 1 and 128 characters. To validate session ids, the easiest way to do it use a function like:
function session_valid_id ( $session_id )
return preg_match ( ‘/^[-,a-zA-Z0-9]$/’ , $session_id ) > 0 ;
>
?>
session_id() itself will happily accept invalid session ids, but if you try to start a session using an invalid id, you will get the following error:
Warning: session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and ‘-,’
8 years ago
session_id() URL-decodes the session value. For example let’s say we use setcookie() to push a cookie down to a web browser. When the browser makes the next page request the browser sends the cookie back up to us with headers like this: Cookie: PHPSESSID=enGHumY%2C-2De-F-TDzNHVmE%2ChY5;
If we use session_id() to read the cookie it will output a value of this: enGHumY,-2De-F-TDzNHVmE,hY5
The two values don’t match! Use either setrawcookie() or URL encode if you wish to match the original value.
12 years ago
I was perplexed by inconsistent results with the session ID depending on whether I retrieve it using SID, COOKIE, or session_id(). I have found that session_id() is the most reliable method, whereas SID and COOKIE[«PHPSESSIONID»] are sometimes undefined.
I used this simple script to quickly test the problem on my servers:
$a = session_id ();
if(empty( $a )) session_start ();
echo «SID: » . SID . «
session_id(): » . session_id (). «
COOKIE: » . $_COOKIE [ «PHPSESSID» ];
?>
Regardless of browser I see the COOKIE undefined on the first load and the other two defined, then SID is empty on subsequent reloads and COOKIE is defined, but session_id() is always defined.
If I insert the session_regenerate_id() method that jeff_zamrzla gives below the refresh the page, I get a new session_id() but the COOKIE value is initially the prior session_id() until I hit refresh a second time. So again, session_id() proves to be the most reliable method.
It’s probably not a bug since I found the behaviour to be consistent in PHP versions 5.2.14, 5.3.3 and 5.3.4, but I can’t figure what I’m missing and hopefully this will help others who run into this.
7 years ago
When session.use_strict_mode is set to 1 or true, you cannot use session_id($sid) to set the session id for the current session.
ini_set ( ‘session.use_strict_mode’ , 1 );
$sid = md5 ( ‘wuxiancheng.cn’ );
session_id ( $sid );
session_start ();
var_dump ( session_id () === $sid ); // always false
?>
8 years ago
This can looks obvious, but as me, you can spend some hours to make a simple session work between different browsers and devices. These are the basics for me, but you can build upon.
if( $_GET ) //defining the session_id() before session_start() is the secret
session_id ( $_GET [ ‘session_id’ ]);
session_start ();
echo «Data: » . $_SESSION [ ‘theVar’ ];
//use your data before below commands
session_destroy ();
session_commit ();
>else //common session statement goes here
session_start ();
$session_id = session_id ();
$_SESSION [ ‘theVar’ ] = «theData» ;
echo «your.php?session_id keyword»>. $session_id ;
>
?>
8 years ago
IMPORTANT NOTE:
If you assign a specific session ID to a user in your applet, then do not run the following code either while logout,
session_regenerate_id(TRUE);
USE:
session_regenerate_id(); instead.
OTHERWISE, setting the session id will no longer works for that user.
20 years ago
Rewriting URL’s is not suggested for obvious security issues. Please be careful with register_globals when using sessions! Check that all information you recieve from a user is valid before accepting it!
12 years ago
If you look at the notes on cookies (set_cookie I think), you will see that you can not read a cookie on the page that it is set. That is because the cookies are sent with the page request which comes, of course, before your PHP is run. You have to wait until the next page request from the same source to read the cookie.
16 years ago
Regarding Colin’s comment, note that setting hash_bits_per_character to 5 results in characters ranging from 0-9 and a-v. Most attackers would be wise enough to realize what was going on when they saw a letter in g-v. The probability of not seeing a letter in g-v is somewhere around 2^-32.
13 years ago
I had a lot of trouble with session_regenerate_id() as it did not regenerate. Session_id() stayed the same no matter what (unless closing the window). I wanted to have different sid and empty vars for each session/page meeting a condition for security reasons. Finally, this worked:
$a = session_id ();
if ( $a == » ) session_start ();
if ( . add check if you want to regenerate and destroy vars on some condition only [ recommended :)]. )
< session_unset (); //destroys variables
session_destroy () //destroys session;
>
$a = session_id ();
if ( $a == » ) session_start ();
if (!isset( $_SESSION [ ‘safety’ ]))
session_regenerate_id ( true );
$_SESSION [ ‘safety’ ] = true ;
>
$_SESSION [ ‘sessionid’ ] = session_id ();
?>
Now you get different sid and session variables empty for each session_start if condition is met (i.e. user hits refresh on user/password form, which I needed badly :). Hope this helps someone out there.
Env: localhost
Note: condition is mandatory, otherwise it destroys on each load.
5 years ago
The call session_id(null) and session_id() provides not the same result. It is imperative to pass no parameters to get correct results.
17 years ago
Length of PHPSESSID appears to be 32 characters by default.
16 years ago
The higher you set session.hash_bits_per_character the shorter your session_id will become by using more bits per character. The possible values are 4, 5, or 6.
When using sha-1 for hashing (by setting ini_set(‘session.hash_function’, 1) the following session string lengths are produced by the three session.hash_bits_per_character settings:
4 — 40 character string
5 — 32 character string
6 — 27 character string
It would seem desirable to use sha-l with 5 bits_per_character because this will emulate a standard 32 character md5 string and make a would-be attacker think that is what you’re hashing with.
17 years ago
In response to simon at quo dot com dot au:
The PHPSESSID is produced using an hash function. By default, it uses MD5 which produces 128 bits long (i.e: 16 bytes long) hashes.
But, since some bytes’ values may not be used in the HTTP header, PHP outputs the hash in its hexadecimal representation, thus resulting in a 32 bytes long text.
Starting with PHP 5.0, you can change the hash function used (by setting «session.hash_function» to whatever function you want to use in php.ini).
You may for example set it to 1 to switch to SHA-1 which produces 160 bits (20 bytes) long hashes.
Please also note that another setting was introduced in PHP 5 (session.hash_bits_per_character) which sort of «compresses» the hash. Thus, resulting in what seems to be a shorter hash.
This feature helps you improve your application’s security by producing IDs that are harder to prodict for a malicious attacker.
12 years ago
Gosh, took a LOOONG time to figure this one out! If you have suhosin built into your PHP and can’t get sessions to work after changing the session id through session_id(), try turning off suhosin’s session encryption option in php.ini with:
18 years ago
Note that Firefox and Mozilla use the same process for launching new windows or tabs, they will pick up the same session id as the previous windows until the parent process dies or is closed. This may cause undesired results if the session id is stored in a db and checked, a solution is to check at the new entry point (new tab or window if the user went back to the index page) for an existing session. If a session id exists and a new one is required use something like:
$ses_id = session_id ();
$bsid_exists = false ;
$bsid_exists = check_session_id_from_db ( $ses_id );
if ( $bsid_exists ) <
//This is a reentry and the session already exists
// create a new session ID and start a new
session_regenerate_id ();
$ses_id = session_id ();
>
?>
18 years ago
About the note from Cybertinus :
The following test doesn’t work, the code following is always executed :
if(! session_id ())
<
// Always executed even if there’s already an opened session
>
session_id () returns an empty string if there is no current session , so to test if a session already exists , it ‘s better to write this :
if(session_id() == «»)
<
session_start();
>
else
<
// Anything you want
>
?>
15 years ago
The documentation for session_id is incomplete when it says:
«For example, the file session handler only allows characters in the range a-z, A-Z and 0-9!».
It is untrue when changing the default for the session.hash_bits_per_character as Colin said. session_id may therefore contain «-» and «,».
12 years ago
In php version 5.3.2 in my case each time a new session-id was generated after session_start() but all was working before correctly in previous versions. So I lost data from my current session (wrong session-id). There was always a $_POST or $_GET or $_COOKIE available with the session-name and session-id, so session_start() was taken this automatically. Now I have to execute session_id(..old id ..) before session_start() and a session is started for the same id.
20 years ago
you can also add the iframe tag:
ini_set(«url_rewriter.tags», «a=href,area=href,frame=src,iframe=src,input=src,form=fakeentry»);
9 years ago
Get a shared session.
Sometimes is good can interchange messages and vars between one session and another, but PHP dont support this. I create this script that allows with session_id() change from current session to shared session (this is, info with scope to all sessions) for read and write info and back in to user session. The code:
ini_set ( ‘display_errors’ , 1 );
error_reporting ( E_ALL );
function get_global ( $key ) //Get current session
if( session_status ()!= PHP_SESSION_ACTIVE ) session_start ();
$current_id = session_id ();
session_write_close ();
//Set a global session with session_id=1
session_id ( 1 );
session_start ();
//Get superglobal value
$value = null ;
if(isset( $_SESSION [ $key ])) $value = $_SESSION [ $key ];
session_write_close ();
//Set the before session
session_id ( $current_id );
session_start ();
return $value ;
>
function set_global ( $key , $value ) //Get current session
if( session_status ()!= PHP_SESSION_ACTIVE ) session_start ();
$current_id = session_id ();
session_write_close ();
//Set a global session with session_id=1
session_id ( 1 );
session_start ();
//Set superglobal value
$_SESSION [ $key ]= $value ;
session_write_close ();
//Set the before session
session_id ( $current_id );
session_start ();
>
//Example
//Begin my session normally
session_start ();
if(empty( $_SESSION [ ‘count’ ])) $_SESSION [ ‘count’ ]= 0 ;
$_SESSION [ ‘color’ ]= «rgb(» . rand ( 0 , 255 ). «,» . rand ( 0 , 255 ). «,» . rand ( 0 , 255 ). «)» ;
>
$_SESSION [ ‘count’ ]++;
$id = session_id ();
//Get the superglobal
$test = get_global ( «test» );
//Set the superglobal test with empty array if this dont set
if( $test == null ) $test =array();
//Get the superglobal
$test = get_global ( «test» );
//Set values for each reload page and save the session_id that create it
$test []= «Value: » . rand ( 0 , 100 ). » SessionID: $id
» ;
//Save the superglobal
set_global ( «test» , $test );
//Show the superglobal
foreach( $test as $t ) echo $t ;
>
echo «Reloads keyword»>. $_SESSION [ ‘count’ ]. «, This my color» ;
- Функции для работы с сессиями
- session_abort
- session_cache_expire
- session_cache_limiter
- session_commit
- session_create_id
- session_decode
- session_destroy
- session_encode
- session_gc
- session_get_cookie_params
- session_id
- session_module_name
- session_name
- session_regenerate_id
- session_register_shutdown
- session_reset
- session_save_path
- session_set_cookie_params
- session_set_save_handler
- session_start
- session_status
- session_unset
- session_write_close
- Copyright © 2001-2023 The PHP Group
- My PHP.net
- Contact
- Other PHP.net sites
- Privacy policy
Phpsessid что это
Модуль сессии поддерживает оба метода. Метод с cookies является оптимальным, но он не всегда доступен. Поэтому PHP предоставляет второй способ, который внедряет идентификатор сессии непосредственно в URL.
PHP умеет преобразовывать ссылки прозрачно. Если session.use_trans_sid включена, все относительные URI-адреса будут автоматически содержать идентификатор сессии.
Замечание:
Директива arg_separator.output из php.ini позволяет настраивать разделитель аргументов. Для полной совместимости с XHTML следует указывать &.
В качестве альтернативы вы можете использовать константу SID , которая устанавливается при запуске сессии. Если клиентское ПО не хранит подходящую сессионную cookie, SID имеет вид session_name=session_id . В противном случае содержит пустую строку. Таким образом, вы можете в любом случае внедрять его в URL.
Приведённый ниже пример демонстрирует, как зарегистрировать переменную и как правильно построить ссылку на другую страницу, используя SID .
Пример #1 Подсчёт количества посещений конкретного пользователя
if (empty( $_SESSION [ ‘count’ ])) $_SESSION [ ‘count’ ] = 1 ;
> else $_SESSION [ ‘count’ ]++;
>
?>Здравствуйте, посетитель, вы видели эту страницу раз.
Функция htmlspecialchars() может использоваться для вывода SID с целью предотвращения XSS-атак.
Вывод SID способом, показанном выше, не является обязательным, если опция —enable-trans-sid была использована при компиляции PHP.
Замечание:
Подразумевается, что неотносительные URL-адреса указывают только на внешние сайты и потому SID к ним не добавляется, т.к. это представляло бы угрозу для безопасности, в частности, риск утечки SID другому серверу.
Phpsessid что это
Сессии представляют набор переменных, которые хранятся на сервере (либо часть на сервере, а часть — в cookie браузера) и которые относятся только к текущему пользователю. В какой-то степени сессии являются альтернативой кукам в плане сохранения данных о пользователе.
Для запуска сессии необходимо вызвать функцию session_start() . Она должна вызываться до отправки ответа пользователю:
При запуске сессии с помощью функции session_start() , если пользователь первый раз заходит на сайт, PHP назначает ему уникальный идентификатор сессии. Этот идентификатор с помощью cookie, которые по умолчанию называются «PHPSESSID», сохраняется в браузере пользователя. С помощью этого идентификатора пользователь ассоциируется с данными сессии. Если для пользователя уже установлена сессия, то данная функция продлевает текущую сессию вместо установки новой.
С помощью специальных функций мы можем получить идентификатор сессии:
session_start(); echo session_id(); // идентификатор сессии echo session_name(); // имя - PHPSESSID
То же значение мы могли бы получить, обратившись к cookie напрямую:
echo $_COOKIE["PHPSESSID"];
Затем для сохранения или получения данных в сессии надо использовать глобальный ассоциативный массив $_SESSION . Сохранение переменной в сессии:
$_SESSION["имя_переменной"] = значение;
Получение сохраненного значения:
$переменная = $_SESSION["имя_переменной"];
Сохранение данных в сессии
Запустим сессию и сохраним в ней значения:
После установки сессии в браузере мы сможем заметить установку специальной куки, которая по умолчанию называется «PHPSESSID»:
SESSION» />SESSION» />
Получение данных сессии
Теперь получим эти значения и выведем на страницу:
session_start(); if (isset($_SESSION["name"]) && isset($_SESSION["age"])) < $name = $_SESSION["name"]; $age = $_SESSION["age"]; echo "Name: $name
Age: $age"; >Удаление данных сессии
Сессия уничтожается с закрытием браузера, однако мы также можем программно удалить либо какие-то отдельные, либо все данные сессии.
Для удаления одной переменной из сессии применяется функция unset() :
session_start(); unset($_SESSION["age"]); // удаляем из сессии переменную "age"
Удалить все данные сессии можно с помощью функции session_destroy() :
session_start(); session_destroy();
Сессия
Сессии — это один из самых важных компонентов, с которыми вам придется работать. Не понимая принципов его работы — наворотите делов. Так что во избежание проблем я постараюсь рассказать о всех возможных нюансах.
Но для начала, чтобы понять зачем нам сессия, обратимся к истокам — к HTTP протоколу.
?? Язык PHP создавался под стать этому протоколу — т.е. основная его задача — это дать ответ на HTTP запрос и «умереть» освободив память и ресурсы. ?? Под HTTP протокол подстроился и механизм сессий, т.о. приходится расчитывать только на себя, ведь сервер при повторном запросе будет забывать обо всём происходящем ранее. ?? И уже как следствие данных , одна из тривиальных задач стоящих перед web-разработчиком это как раз следить за этой самой сессией.
Вот вам статейка на тему PHP is meant to die, или вот она же на русском языке, но лучше отложите её в закладки «на потом».
Перво-наперво необходимо «стартовать» сессию — для этого воспользуемся функцией session_start(), создайте файл session.start.php со следующим содержимым:
session_start();Запустите встроенный в PHP web-server в папке с вашим скриптом:
php -S 127.0.0.1:8080Запустите браузер, и откройте в нём Developer Tools или что там у вас, далее перейдите на страницу http://127.0.0.1:8080/session.start.php — вы должны увидеть лишь пустую страницу, но не спешите закрывать — посмотрите на заголовки которые нам прислал сервер:

Там будет много чего, интересует нас только вот эта строчка в ответе сервера (почистите куки, если нет такой строчки, и обновите страницу):
Set-Cookie: PHPSESSID=dap83arr6r3b56e0q7t5i0qf91; path=/Увидев сие, браузер сохранит у себя куку с именем PHPSESSID :

PHPSESSID — имя сессии по умолчанию, регулируется из конфига php.ini директивой session.name, при необходимости имя можно изменить в самом конфигурационном файле или с помощью функции session_name()
И теперь — обновляем страничку, и видим, что браузер отправляет эту куку на сервер, можете попробовать пару раз обновить страницу, результат будет идентичным:

Итого, что мы имеем — теория совпала с практикой, и это просто отлично.
Следующий шаг — сохраним в сессию произвольное значение, для этого в PHP используется супер-глобальная переменная $_SESSION , сохранять будем текущее время — для этого вызовем функцию date():
session_start(); $_SESSION['time'] = date("H:i:s"); echo $_SESSION['time'];Обновляем страничку и видим время сервера, обновляем ещё раз — и время обновилось. Давайте теперь сделаем так, чтобы установленное время не изменялось при каждом обновлении страницы:
session_start(); if (!isset($_SESSION['time'])) < $_SESSION['time'] = date("H:i:s"); > echo $_SESSION['time'];Обновляем — время не меняется, то что нужно. Но при этом мы помним, PHP умирает, значит данную сессию он где-то хранит, и мы найдём это место.
Всё тайное становится явным
По умолчанию, PHP хранит сессию в файлах — за это отвечает директива session.save_handler, путь по которому сохраняются файлы ищите в директиве session.save_path, либо воспользуйтесь функцией session_save_path() для получения необходимого пути.
В вашей конфигурации путь к файлам может быть не указан, тогда файлы сессии будут хранится во временных файлах вашей системы — вызовите функцию sys_get_temp_dir() и узнайте где это потаённое место.
Так, идём по данному пути и находим ваш файл сессии (у меня это файл sess_dap83arr6r3b56e0q7t5i0qf91 ), откроем его в текстовом редакторе:
time|s:8:"16:19:51";Как видим — вот оно наше время, вот в каком хитром формате хранится наша сессия, но мы можем внести правки, поменять время, или можем просто вписать любую строку, почему бы и нет:
time|s:13:"\m/ (@.@) \m/";Для преобразования этой строки в массив нужно воспользоваться функцией session_decode(), для обратного преобразования — session_encode() — это зовется сериализацией, вот только в PHP для сессий — она своя — особенная, хотя можно использовать и стандартную PHP сериализацию — пропишите в конфигурационной директиве session.serialize_handler значение php_serialize и будет вам счастье, и $_SESSION можно будет использовать без ограничений — в качестве индекса теперь вы сможете использовать цифры и специальные символы | и ! в имени (за все 10+ лет работы, ни разу не надо было 🙂
Напишите свою функцию, аналогичную по функционалу session_decode() , вот вам тестовый набор данных для сессии (для решения знаний регулярных выражений не требуется), текст для преобразования возьмите из файла вашей текущей сессии:
$_SESSION['integer var'] = 123; $_SESSION['float var'] = 1.23; $_SESSION['octal var'] = 0x123; $_SESSION['string var'] = "Hello world"; $_SESSION['array var'] = array('one', 'two', [1,2,3]); $object = new stdClass(); $object->foo = 'bar'; $object->arr = array('hello', 'world'); $_SESSION['object var'] = $object; $_SESSION['integer again'] = 42;Так, что мы ещё не пробовали? Правильно — украсть «печеньки», давайте запустим другой браузер и добавим в него теже самые cookie. Я вам для этого простенький javascript написал, скопируйте его в консоль браузера и запустите, только не забудьте идентификатор сессии поменять на свой:
javascript:(function( )document.cookie='PHPSESSID=dap83arr6r3b56e0q7t5i0qf91;path=/;';window.location.reload();>)()Вот теперь у вас оба браузера смотрят на одну и туже сессию. Я выше упоминал, что расскажу о способах защиты, рассмотрим самый простой способ — привяжем сессию к браузеру, точнее к тому, как браузер представляется серверу — будем запоминать User-Agent и проверять его каждый раз:
session_start(); if (!isset($_SESSION['time'])) < $_SESSION['ua'] = $_SERVER['HTTP_USER_AGENT']; $_SESSION['time'] = date("H:i:s"); > if ($_SESSION['ua'] != $_SERVER['HTTP_USER_AGENT']) < die('Wrong browser'); > echo $_SESSION['time'];Это подделать сложнее, но всё ещё возможно, добавьте сюда ещё сохранение и проверку $_SERVER[‘REMOTE_ADDR’] и $_SERVER[‘HTTP_X_FORWARDED_FOR’] , и это уже более-менее будет похоже на защиту от злоумышленников посягающих на наши «печеньки».
Ключевое слово в предыдущем абзаце похоже, в реальных проектах cookies уже давно «бегают» по HTTPS протоколу, таким образом никто их не сможет украсть без физического доступа к вашему компьютеру или смартфону
Стоит упомянуть директиву session.cookie-httponly, благодаря ей сессионная кука будет недоступна из JavaScript’a. Кроме этого — если заглянуть в мануал функции setcookie(), то можно заметить, что последний параметр так же отвечает за HttpOnly. Помните об этом — эта настройка позволяет достаточно эффективно бороться с XSS атаками в практически всех браузерах.
Задание%accordion% Добавьте в код проверку на IP пользователя, если проверка не прошла — удалите скомпрометированную сессию. %/accordion%
По шагам
А теперь поясню по шагам алгоритм, как работает сессия в PHP, на примере следующего кода (настройки по умолчанию):
session_start(); $_SESSION['id'] = 42;- после вызова `session_start()` PHP ищет в cookie идентификатор сессии по имени прописанном в `session.name` — это `PHPSESSID`
- если нет идентификатора — то он создаётся (см. session_id()), и создаёт пустой файл сессии по пути `session.save_path` с именем `sess_`, в ответ сервера будет добавлены заголовки, для установки cookie `=`
- если идентификатор присутствует, то ищем файл сессии в папке `session.save_path`:
- не находим — создаём пустой файл с именем `sess_` (идентификатор может содержать лишь символы из диапазонов `a-z`, `A-Z`, `0-9`, запятую и знак минус)
- находим, читаем файл и распаковываем данные (см. session_decode()) в супер-глобальную переменную `$_SESSION` (файл блокируется для чтения/записи)
- когда скрипт закончил свою работу, то все данные из `$_SESSION` запаковывают с использованием `session_encode()` в файл по пути `session.save_path` с именем `sess_` (блокировка снимается)
Задание%accordion% Задайте в вашем браузере произвольное значение куки с именем PHPSESSID , пусть это будет 1234567890 , обновите страницу, проверьте, что у вас создался новый файл sess_1234567890 %/accordion%
А есть ли жизнь без «печенек»?
PHP может работать с сессией даже если cookie в браузере отключены, но тогда все URL на сайте будут содержать параметр с идентификатором вашей сессии, и да — это ещё настроить надо, но оно вам надо? Мне не приходилось это использовать, но если очень хочется — я просто скажу где копать:
- session.use_cookies
- session.use_only_cookies
А если надо сессию в базе данных хранить?
Для хранения сессии в БД потребуется изменить хранилище сессии и указать PHP как им пользоваться, для этой цели создан интерфейс SessionHandlerInterface и функция session_set_save_handler.
Отдельно замечу, что не надо писать собственные обработчики сессий для redis и memcache — когда вы устанавливаете данные расширения, то вместе с ними идут и соответствующие обработчики, так что RTFM наше всё. Ну и да, обработчик нужно указывать до вызова session_start() 😉
Задание%accordion% Реализуйте SessionHandlerInterface для хранения сессии в MySQL, проверьте, работает ли он. Это задание со звёздочкой, для тех кто уже познакомился с базами данных. %/accordion%
Когда умирает сессия?
За время жизни сессии отвечает директива session.gc_maxlifetime. По умолчанию, данная директива равна 1440 секундам (24 минуты), понимать её следует так, что если к сессии не было обращении в течении заданного времени, то сессия будет считаться «протухшей» и будет ждать своей очереди на удаление.
Интересен другой вопрос, можете задать его матёрым разработчикам — когда PHP удаляет файлы просроченных сессий? Ответ есть в официальном руководстве, но не в явном виде — так что запоминайте:
Сборщик мусора (garbage collection) может запускаться при вызове функции session_start() , вероятность запуска зависит от двух директив session.gc_probability и session.gc_divisor, первая выступает в качестве делимого, вторая — делителя, и по умолчанию эти значения 1 и 100, т.е. вероятность того, что сборщик будет запущен и файлы сессий будут удалены — примерно 1%.
Задание%accordion% Измените значение директивы session.gc_divisor так, чтобы сборщик мусора запускался каждый раз, проверьте что это так и происходит. %/accordion%
Самая тривиальная ошибка
Ошибка у которой более полумиллиона результатов в выдаче Google:
Cannot send session cookie — headers already sent by Cannot send session cache limiter — headers already sent
Для получения таковой, создайте файл session.error.php со следующим содержимым:
echo str_pad(' ', ini_get('output_buffering')); session_start();Во второй строке странная «магия» — это фокус с буфером вывода, я уже рассказывал о нём в одноимённой главе. Да-да, мы забиваем этот буфер пробелами до длинны в 4096 символов
Запустите, предварительно удалив cookie, и получите приведенные ошибки, хоть текст ошибок и разный, но суть одна — поезд ушёл — сервер уже отправил браузеру содержимое страницы, и отправлять заголовки уже поздно, это не сработает, и в куках не появилось заветного идентификатора сессии. Если вы стокнулись с данной ошибкой — ищите место, где выводится текст раньше времени, это может быть пробел до символов <?php , или после ?> в одном из подключаемых файлов, и ладно если это пробел, может быть и какой-нить непечатный символ вроде BOM, так что будьте внимательны, и вас сия зараза не коснется (как-же, … гомерический смех).
Задание%accordion% Для проверки полученных знаний, я хочу, чтобы вы реализовали свой собственный механизм сессий и заставили приведенный код работать:
require_once 'include/sess.php'; sess_start(); if (isset($_SESS["id"])) < echo $_SESS["id"]; > else < $_SESS["id"] = 42; >Блокировка
Ещё одна распространённая ошибка у новичков — это попытка прочитать файл сессии пока он заблокирован другим скриптом. Собственно, это не совсем ошибка, это недопонимание принципа блокировки 🙂
Но давайте ещё раз по шагам:
- `session_start()` не только создаёт/читает файл, но и блокирует его, чтобы никто не мог внести правки в момент выполнения скрипта, или прочитать не консистентные данные из файла сессии
- блокировка снимается по окончанию выполнения скрипта
«Воткнутся» в данную ошибку очень легко, создайте два файла:
// файл start.php session_start(); echo "OK";// файл lock.php session_start(); sleep(10); echo "OK";Теперь, если вы откроете в браузере страничку lock.php , а затем в новой вкладке откроете start.php то увидите, что вторая страничка откроется только после того, как отработает первый скрипт, который блокирует файл сессии на 10 секунд.
Есть пару вариантов, как избежать подобного явления — «топорный» и «продуманный».
«Топорный» Использовать самописный обработчик сессий, в котором «забыть» реализовать блокировку 🙂 Чуть лучше вариант, это взять готовый и отключить блокировку (например у memcached есть такая опция — memcached.sess_locking) O_o Потратить часы на дебаг кода в поисках редко всплывающей ошибки.
«Продуманный» Куда как лучше — самому следить за блокировкой сессии, и снимать её, когда она не требуется:
— Если вы уверенны, что вам не потребуется вносить изменения в сессионные данные используйте опцию read_and_close при старте сессии:
session_start([ 'read_and_close' => true ]);Таким образом, блокировка будет снята сразу по прочтению данных сессии.
— Если вам таки нужно вносить изменения в сессию, то после внесения оных закрывайте сессию от записи:
session_start(); // some changes session_write_close();Задание%accordion% Чуть выше был приведён листинг двух файлов start.php и lock.php , создайте ещё файлы read-close.php и write-close.php , в которых вы будете контролировать блокировку перечисленными способами. Проверьте как работает (или не работает) блокировка. %/accordion%
В заключение
В этой статье вам дано семь заданий, при этом они касаются не только работы с сессиями, но так же познакомят вас с MySQL и с функциями работы со строками. Для усвоения этого материала вам хватит мануала по приведенным ссылкам — никто за вас его читать не будет. Дерзайте!
