PHP: как не потерять сессию

8 февраля 2011 г.

Достаточно часто встречается ситуация, когда авторизованный пользователь уходит из-за компьютера или просто переключается на какую-либо другую задачу, забывая при этом периодически покликивать по ссылкам сайта. Результат: по возвращении к работе с сайтом после первого же клика его нагло выбрасывает из теплой и уютной админки с нахальным требованием залогиниться заново.
Разрыв PHP сессииВо время разработки моего последнего проекта подобные ситуации с пользователями также происходили. Согласен, обидно, когда набираемый и корректируемый в течение получаса текст вдруг уходит в небытие и никакими силами его уже не спасти. Решив раз и навсегда покончить с этой проблемой (в конце-то концов сайты делаются, собственно, для их посетителей), я набросал несколько строк кода. И — о чудо! — проблема решилась.

Прочему происходит разрыв сессии

Здесь все просто. Сессия рвется потому, что веб-сервер старается держать только сессии активных пользователей. Активными, по его мнению, считаются те, которое запрашивают у него новые страницы не реже, чем… указано в настройках сервера. Как правило, эта настройка записывается там, куда не имеет доступа даже арендатор сервера.

Можно, конечно, забрасывать письмами админов хостера с требованием увеличить время сессии, а то и сделать ее бесконечной, но мало кто на это пойдет. Подвергать такому риску свои сервера хостер будет только в том случае, если Вы неслабо платите за его услуги. Если же у Вас простой виртуальный хостинг — на положительный ответ можете даже не надеяться. Значит, пойдем другим путем.

Как поддержать сессию автоматически

Теперь, когда мы знаем, что для поддержания сессии нужно всего лишь периодически запрашивать у сервера какие-нибудь данные, решение напрашивается само собой. Нужно просто запрашивать эти самые данные. Это можно делать вручную, кликая по каким-нибудь ссылкам в новых вкладках браузера, в этом случае сессия будет поддерживаться и в той вкладке, где тихо и меланхолично набирается какой-нибудь текст в WYSIWYG-редакторе. Но попробуйте-ка все это растолковать пользователю, который кроме браузера ничего особо и не знает. Он решит, что Вы хотите над ним просто поиздеваться, отправит Вас без снаряжения в пешее эротическое и забьет на Ваш ресурс. И правильно, кстати, сделает! Нехорошо в наши дни заставлять пользователя заниматься таким грязным делом.

Но идея-то с поддержкой сессий таким вот образом — хороша! Настолько хороша, что от нее совершенно не хочется отказываться. А мы отказываться от нее и не будем. Отправлять запросы серверу браузер будет самостоятельно, без какого-либо пользовательского участия. Он просто будет информировать сервер, мол, эй, я живой, не рви мою сессию и сервер его прекрасно поймет. Это чем-то похоже на команду ping, когда клиент просто сообщает о своем присутствии — и ничего больше. Потому этот скрипт я так и решил обозвать — пингер.

Пингер: клиентская сторона

Повторюсь. Для того, чтобы сервер не рвал сессию пользователя, нам нужно периодически запрашивать у сервера какие-либо данные. Желательно, как можно меньших объемов, поскольку эти самые данные нам не нужны. Нам нужно лишь «отметиться» на сервере. Поэтому воспользуемся обычным post-запросом с помощью jQuery:

$(document).ready(function() {
var result = '';
setInterval(pinger, 300000);
});

function pinger()
{
$.post("/ajax/pinger.php", function(result) {
});
}

Вход в админ панельПосле создания HTML-документа у нас запустится код, заключенный в $(document).ready(). А это значит, что каждые 5 минут (5 x 60 x 1000 = 300000 миллисекунд) будет выполняться функция pinger(), в которой и размещается наш post-запрос. Давайте немного разберем, что и как он делает.

.post( url, [data], [callback], [type] )

Первый (обязательный) параметр — это URL страницы, к которой мы обращаемся. Ее код я дам чуть позже. Второй — данные, передаваемые скрипту на сервер. Третий — функция, которая выполнится после выполнения запроса (нам оно сейчас не надо). И, наконец, четвертый — тип передаваемых данных (XML, JSON, HTML etc). Функцию во втором параметре я оставил на всякий случай — скорее всего мне на боевом проекте понадобится не только «пинговать».

Пингер: серверная сторона

Ну а здесь совсем просто. Запускаем сессию, выводим что-нибудь, чтобы не отдавать пустой документ:

session_start();
echo 'ok';
session_write_close();

Не пугайтесь, уважаемый читатель. Последней инструкцией мы ни в коем случае не убиваем сессию. Мы всего лишь навсего открываем к ней доступ для других скриптов. Вся наша сессия, все данные в ней успешно остаются храниться в ней же. А вот «свежесть» сессии успешно обновляется, что нам, собственно, и нужно.

Результат работы пингера

Результатом работы этого пингера стало отсутствие жалоб от пользователей на «вылетание» админки сайта. А это куча сэкономленных нервов и времени на разъяснения, почему такое происходит. Работает — и работает, пользователь даже не замечает этого. Чего, собственно, я и добивался.

Теги: рубрика Сайтостроение