Как стать автором
Обновить

Комментарии 58

Хм, сперва полагал, что речь идёт о юзабилити-примерах, а тут программирование. Было бы неплохо пояснить, о чём речь в статье далее до ката.
Спасибо.
спасибо, написал немного яснее о чём речь
Про хэш не задумывался даже. Между сессием и get-параметром выбрал сессию. Может позже на хэш переделаю. Спасибо
а я вот от сессии отказался из за кеширования, пользовался гетом, но соответственно баги при возврате по хистори

хэш действительно хороший вариант
Это кеширование мешает только в опере. Я на него внимания не обращаю. И как уже сказали ниже я в сессию сохраняю и адрес страницы на которой показывать уведомление. Проблем не замечено
Можно еще куку вешать.
Ее уже можно и из js проверять и на стороне сервера, в зависимости от задачи.
с кукой есть проблемы примерно как с сессией, только более ярко выраженные,
например если куку снимать при показе страницы после редиректа, то если странице не дать открыться, — уведомление вылезет уже позже в неподходящем случае
Куку можно вешать с очень маленьким ttl и/или уникальную для страницы, например со значением урала самой страницы.
Перекуем мечи на урала! =)
куку нужно вешать с такой областью видимости чтобы она только на целевой странице и была доступна. с маленьким TTL это решит вопрос с «запоздалым проявлением», а если в ней передавать «идентификатор сообщения» (которые хранятся отдельно) то это решит и проблемы одновременным открытием нескольких страниц с разыми сообщениями.
где холивар насчет того, что у пользователя JS отключен? :)
можно отмазаться тем что ничего страшного без JS по сути и не произойдёт :) просто небольшая деградация интерфейса
Пользователей без JS в учет не беру, для меня это тоже самое что и верстать под IE6
на мобильниках JS полноценного нет
Сайту на мобильном — отдельная версия
это устаревший подход — сейчас из-за наличия нетбуков и коммуникаторов нет уже четкой границы между desktop и мобильником
Для борьбы с открытием нескольких окон — кто мешает сохранять более полные данные в сессии? Не только сам факт редиректа (show_notice=1), но и адрес страницы, куда перекидывается юзер (location=$location)? Если откроет несколько страниц — нотификашка покажется только на той, у которой совпадает URI.

А если при открытии окна сразу убирать обе переменные из сессии — тогда вообще даже при повторном открытии окна (по F5) ничего не покажется.
Это тоже не панацея :) (для кук в большей степени, для сессии это надо умудрится, но теоретически тоже можно)

1. меня кидает на /a.php
2. я не даю ей загрузится (тупо кликаю по закладке и ухожу в другое место), т.е. JS-ы которые удалят куки не выполняются
3. гуляю по сайту, захожу на /a.php — и вижу уведомление. не очень к месту :)

Это можно лечить таймаутами — но опять же, на глючном GPRS-е страница может 30 секунд запросто грузиться. А для быстрого интернета за 30 секунд вполне можно вопсроизвести описанный ранее глюк :)

Если чесно, все эти заморочки не стоят своей разработки.
Да и проблемы при использовании сессии или кук появляются как раз от того что это неподходящее место для такой информации.
Погоди, при чем здесь JS? Наверное слово «окно» сбило с толку… Я говорю о выполнении этих вещей на сервере. Идет запрос на открытие страницы (шлются заголовки от браузера), PHP-парсер отрабатывает страницу, видит из переменных сессии, что стоит редирект на вызываемую страницу. Ну и далее — он сначала убирает 2 теперь уже лишние переменные из сессии и выдает страниы с примечанием наверху. Всё, при следующем обращении на эту же страницу ничего не показывается. При обращении на соседние страницы оно в принципе не отобразится — поскольку мы запомнили, куда именно надо показать инфу.
ну да, всё правильно, с сессией на практике всё сильно лучше чем с куками (хотя логически проблемы те же)

Мне просто по жизни механизм кэширование мешает пользоваться сессией, и я её как-то мысленно всё время отбрасываю.
Хотя когда такой проблемы нет, сессия и без лишних заморочек отлично справляется — очень удобно, — можно в любом месте кода добавлять туда уведомления и не думать когда произойдёт редирект.
Чем пользуешься для кеширования? Кеширование ведь надо параметризовывать — хотя бы для того, чтобы не отдавать одну и ту же инфу залогинены пользователям и гостям.
всё самописное, и с параметризацией всё порядке.

проблема, как я сейчас вспомнил, была немного хитрее — у меня поиск кэшировал редирект на страницу с результатом, — т.е. при попадании в кэш редирект происходил, а вот в сессию сообщение уже никто не писал, решение сохранять вместе с редиректом часть сессии показалось уж слишком странным, — тут-то и начались изыскания :)
Не совсем понял, что значит «кешировал редирект»? Ты делаешь поиск по базе, получаешь данные, и на основании того, что в этих данных только 1 запись — делаешь редирект. Так ведь? Где в этой цепочке кеш?
Кэширование идёт на самом верхнем уровне, до поиска
1. приходит запрос /search?q=вася
2. я к нему дописываю зависимости (например признак того что это страница для гостя)
3. смотрю нет ли чего у меня в кэше по такому запросу,
4. и не лазя в базу отдаю редирект
Собсно, взяв на шаге 3 данные, приписываешь в сессию пару переменнх и отдаешь редирект. Не знаю подробностей устройста, конечно… однако примерно — так.
А никто не задумывался, что подобная проблема (notice'ы) возникает только если движок криво оперирует данными?

Я имею ввиду, например когда у программиста нет возможности на самой странице результатов поиска написать что-то типа:
if (только один вариант) {
показать(notice);
обработать_и_показать(только один вариант);
} else {
показать все результаты поиска;
}

и не будет проблем с никакими редиректами типа header:Location или document.location.
я правильно понимаю что предлагается по урлу поиска ( например localhost/search? параметры) показывать найденную страницу?

на мой вкус это не хорошо хотя бы тем что нельзя дать нормальную ссылку на эту страницу,
всё таки если в результате поиска находится страница про Васю, то и отображатся она должна по соответствующему URL-у: например localhost/pages/Вася
Эк мы с тобой одновременно светлые мысли кидаем… :)))
Если с точки публичного поиска — то да, Вы правы.
Но если поиск внутри, например, админ-панели, то помоему намного лучше избавляться от любых редиректов любыми силами.
Насчет того, что нельзя дать URL на страницу результатов — неправда, можно. Сомневаюсь что параметры в запрос поиска Вы будете передавать POSTом :)
Часто бывает, что за поиск данных и за их отображение отвечают разные модули системы. В этом слуае при поиске проще обработать количество найденного и переправить посредством стандартного заголовка HTTP.

Есть и более прозаическая причина — ЧПУ (ЧеловекоПонятныйУрл). У поиска и у конкретной страницы с данными разные урлы. Соответственно, если статья о Пупкине лежит по адресу site.com/people/pupkin/, то урл поиска — по адресу site.com/search/?subj=Пупкин. Выдавать одну и ту же страницу (про Васисуалия) по двум разным урлам — это не совсем правильно. Почему неправильно — есть разные причины, это тема отдельного большого топика.
Ответил выше.

Насчет разных модулей системы и того, что Вы не можете из одного модуля вызвать инициализацию другого — ну это явно же проблема движка (а точнее его отсутствия).

Хотя, даже если поиск доступен публике (поисковому боту). Я не уверен что он так просто в строку поиска введет «Вася пупкин» и получит вторую страницу идентичную ЧПУ Пупкину. И если Вы даже светите ссылку на site.com/search/?subj=Пупкин — что мешает Вам добавить во время поиска:

link rel=«canonical» href=«hvosting.ua/hosting.html»

или вообще закрыть к индексации /search/*
Про инициализацию — никто не говорит, что нельзя вызвать один из другого. Нормальная система сможет это сделать легко. Вопрос в нагромождении взаимных вызовов и, как следствие, усложнение логики, появление нетривиальных ошибок «на стыке» модулей.
Мой point в том, что поведение системы не должно быть сложным. Отработал модуль — выдал результат. В нашем случае результат — одна ссылка. И мы за пользователя просто делаем следующий шаг — «нажимаем» на ссылку и попадаем куда надо. Так вот это «нажатие» не должно происходить посреди алгоритмов и вызовов. Чем ближе «к поверхности», тем проще.

Насчет УРЛов — xnj tcnm URI (URL) — Unified Resource Identifier (Locator). Т.е. это унифицированное ID ресурса. Есть ресурс — страница о В. Пупкине — у него должен быть унифицированный (и, по возможности, уникальный) идентификатор. А так получится большое множество — по числу вариантов нахождения странице о Васе.
Хотя по этому пункту не буду настаивать — это полу-религиозный вопрос :)
Я использую тоглько 2й вариант (1й — муть, а 3й требует яваскрипта который нафиг не вперся ради такой мелочи). Только передавать удобее не цифры и ид, например: Location: /login.php?msg=need_login
Второй вариант проигрывает 3-му тем что пользователи начинают друг-другу давать ссылки на страницы с открытым уведомлением, хотя сторонним людям оно нафиг не упало ( пример: moikrug.ru/companies/571544408/?one=1 ). Но эта проблема не касается страниц на которые ссылок не дают ( ну например внутренние страницы какой-нибудь админки )

1-й вариант очень удобен как универсальное решение для всего сайта, могу объяснить почему если интересно
Насчет ссылок — да, тоже верно (( Тогда предлагаю дополнительно ставить короткоживущую куку к ссылке (просто кука — не совместима с открытием страницы в нескольких окнах параллельно).

А заводить ради этого сессию считаю неразумным все же.

> 1-й вариант очень удобен как универсальное решение для всего сайта, могу объяснить почему если интересно

Конечно интересно, попробуйте :)
Мне кажется не совсем правильным перенаправлять пользователя на страницу Васи, даже если он всего один такой. Почему? Потому что это нарушает ожидания пользователя — он возможно просто хотел проверить файт наличия Васи (и число этих Вась), а не получать целую статью с картинками про него — зачем его заваливать бесполезной информацией. То есть мне кажется, это весьма спорное решение и подходит не везде и не всем…
Да, конечно, это довольно редкий случай когда имеет смысл так делать.
Собственно я и выбрал этот пример для статьи о нотификациях, потому что в нём без нотификатора ну никак не обойтись.
Спасибо.
В этом и суть уведомлений в данном примере — показать, что это уже не страница поиска, что система решила упростить жизнь пользователю, но он может вернуться.
Если вы не делаете перенаправлений, то и уведомления вам не нужны.
Мне кажется не совсем правильным перенаправлять пользователя на страницу Васи, даже если он всего один такой

А я бы сказал что редко когда это неправильно.

К примеру, на «каталогах» меня напрягает то, что я *точно* знаю что мне надо, я ищу это, а получаю страницу результатов. Например, ищем «после прочтения сжечь». В данном случае релевантность первой записи более чем гигантская, всё остальное очевидно не подходит даже для сравнения.
Могу предложить ещё такое извращение — использовать 2-й способ, но при загрузке делать редирект на страницу без мусорного параметра, а на ней смотреть REFERER =)
Устранены все проблемы, кроме F5.

Я использую сессии.
у существенного процента пользователей REFERRER отшиблен файерволом(или типа того).
вот такая вот паранойя :(

ну и такой метод требует refresh страницы, а hash убирается без перезагрузки.
«пользователи начнут давать друг другу ссылки с »?show_notice=1" — это уже не очень приятно"

надо HTTP_REFERER && show_notice проверять
тогда эта проблема исчезает
REFERER очень много у кого не работает из-за файерволов (и прочих InternetSecurity) и корпоративных проксей
и как же проверять родителя линка?
для статистики хватит тех у кого он не отрублен.
в логике сайта полагаться на REFERER нельзя.
я бы выбрал вариант с cookie.

сессия для каждого пользователя — слишком дорогое удовольствие для высоконагруженных проектов.

$_GET не очень удобен в смысле шаринга ссылок и рефреша страницы

javascript здесь не кажется идеологически верным вариантом (всё же он отвечает за поведение элементов на странице, а не их состав).
храненение информации не в урле мешает кэшированию страниц. а это куда важнее сессионого хранилища для нагруженного проекта
Я почему-то думал, что в статье будет приведен такой пример:
function doRedirect($location) {
    header("X-Show-Notice: show");
    header("Location: $location");
}
X-Show-Notice: show

Будет выдано браузеру. Стало быть, обработку этого сообщения надо сделать силами, опять же, браузера. Можете привести работу JS-срипта для обработки этого заголовка?
что-то я сегодня не проснулся еще :)
Заголовок X-Show-Notice будет радостно проигнорирован браузером, который получит 302-ой код от сервера и тут же пошлет следующий гет-запрос по указанному в Location адресу.
Если кто выбрал Codeigniter своим фреймворком, то в нём есть удобный инструмент работы с такими сообщениями: Flashdata. Значение сохраняется только для следующей страницы и потом автоматически удаляется.
В подобной ситуации всегда пользовался модифицированным первым вариантом. Причём в $_SESSION['messages'] хранится массив вида: ('/news/253/'=>'Новость успешно добавлена') (не знаю как и зачем передавать просто флаг о сообщении, причём непоятно о каком). В нужном месте проверить текущий url на присутствие в messages, вывести и удалить url из массива в сессии. Всё просто. На сервере сразу будет видно, что результат поиска один и что будем редиректить сразу на /Вася_Пупкин/, следовательно запись такая: ('/Вася_Пупкин/'=>'Нашлась только.....').
А в js втюхивать что-то — рука не подымится. А отключенный js? А i18n? Да и мороки больше. Можно, конечно, при желании генерировать нужный js-словарь сообщений при обращении, но это уже другая тема.
пример с флагом о просто сообщении приведён для простоты
отключенный JS это тема отдельного холивара
а js словарь всё равно придётся делать если есть js и i18n :)
мне кажется, если не самый легкий, то самый прямой (с наименьшим количеством костылей) вариант хранить нотификации в бд, да, данные будут пухнуть, но с этим можно что-то придумать Т.е. объекты системы могут нотифаить пользователю, а сам нотификатор забирает сообщения из базы и показывает, при этом выбранные к показу собщения можно либо сразу удалять из бд, либо ставить флажок «прочитано». С таким подходом мы обретаем и несколько дополнительных возможностей, например, нотификации, которые показываться до выполнения определенного условия (например «заполните номер телефона в профиле», «подтвердите введенный емейл»:) или в определенное время (можно повесить нотификацию которую пользователь должен будет увидеть через месяц).
а для гостя как сообщения к пользователю привязывать? по id сессии? тогда это и есть просто сессия, которая хранится в БД :)
у автора очень простой пример, случаев когда полезно захардкодить сообщения прямо в шаблон/код можно придумать не много. Поэтому предложенное решение скорее костыль для такой вот конкретной ситуации. А когда вам надо передать сообщений 5-10 или чтото более контекстнозависимое изобразить, то я думаю такой вариант не подойдет
пример описывает частый случай нагруженной гостевой страницы на которой обязательно должно быть кэширование, которое плохо уживается с передачей сообщений через сессию (можно, но страшно костыльно).
Кстати не обязательно делать сообщения предвбитыми, на JS вполне можно сделать схему не менее гибкую чем на базе сессии в PHP.

5-10 сообщений могут вылезти только в каком-нибудь внутреннем залогиновом интерфейсе, тут безусловно удобнее делать реализацию через сессию например как в Codeigniter::Flashdata.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации