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

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

Конечно первый вариант. Без вариантов вообще :)
На самом деле есть варинты, конечно. Нужно делать так как делают 50% веб-сайтов (и ваш в том числе) не задумывась ни на минуту:

$ telnet http://www.apache.org 80
Trying 140.211.11.130...
Connected to http://www.apache.org (140.211.11.130).
Escape character is '^]'.
GET http://www.apache.org/dist HTTP/1.0
Host: http://www.apache.org

HTTP/1.1 301 Moved Permanently
Date: Mon, 10 Dec 2007 11:46:25 GMT
Server: Apache/2.3.0-dev (Unix)
Location: http://www.apache.org/dist/
Cache-Control: max-age=86400
Expires: Tue, 11 Dec 2007 11:46:25 GMT
Vary: Accept-Encoding
Content-Length: 316
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://www.apache.org/dist/">here</a>.</p>
<hr>
<address>Apache/2.3.0-dev (Unix) Server at http://www.apache.org Port 80</address>
</body></html>

Всё просто: если браузер не отрабатывает редиректы (да, есть и такие), то ссылку человук увидит. А если отрабатывает - то ничего и не мельтешит!
Первый. Раздражает на такие ссылки смотреть.
Подождите, сейчас Вы будете перемещены...
Первый вариант требует более строгого подхода, но он однозначно=)
А можно поподробнее про подход? :-)
http://ru2.php.net/manual/ru/function.he…
Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP. It is a very common error to read code with include(), or require(), functions, or another file access function, and have spaces or empty lines that are output before header() is called. The same problem exists when using a single PHP/HTML file.

Короче, надо следить чтоб контента не было перед отдачей header();
А… Ну это понятно :-) Он просто работать не будет и скажет, что «Headers already sent».
Ну на самом деле это серьезная ошибка=)
Поэтому ИМХО рекомендуется использовать буфферные функции - типа ob_start() =)
Да ни в коем случае. Буферные функции вещь мощнейшая, но никак не для этих целей.
Эта же проблема решается элементарно грамотным построением сценария.
Почему ни в коем случае?=) Это зависит от того, кто с чем сталкивается в работе - это во-первых (я говорю про чужой код, например), а во-вторых, бывает так, что гораздо удобнее использовать буфер и заголовки, нежели перестраивать сценарий=)
Подгонка чужого кода и перенастройка кривых сценариев к этому не относится. Там и не на такие сделки с дьяволом приходится идти, чтобы хоть как то работало в сжатые сроки.
Буферизация же жрет ресурсы и время до окончания сценария, в которое браузер бы уже спокойно начал бы отрисовывать пользователю страницу.
Конечно, человек, который разбирается во всех нюансах может делать как считает нужным в данной ситуации, но не нужно рекомендовать подобные вещи новичкам.
При грамотном построении сценария согласно MVC(Model - View - Controller), все необходимые данные обрабатываются и подготавливаются _до_ непосредственного их вывода в браузер. В таком случае использование жрущую ресурсы ob_start() становится ненужным.

Пример:





...

...

...

Это всё понятно. Обсуждается две модели - модель заведомо неправильного чужого кода и своя модель. В своей модели я не допущу ob_start для такой фигни, а при правке чужого кода гораздо быстрее использовать буферизацию в случае невозможности внести правку без переписывания большого количества кода, чтобы сдать проект в сроки (сфера SEO).
Понимаю, что вы хотите сказать. Но это скорее не удобство использования, а некая в случае, когда невозможно/лень/долго переписывать сценарий в правильной структуре.
Но это, безусловно, костыль.
а, ну да
не заметил второй комментарий

Кстати, пример отображает только точки=(
Да, заметил. По всей видимости, хабровская анти-XSS порезала все теги. Но смысл, вижу, вы знаете.
RTFM :)
php.ini _ output_buffering.
имхо так проще...
НЛО прилетело и опубликовало эту надпись здесь
Ну, допустим, у меня есть форма, в которой action указывает на страницу с php-скриптом, который осуществляет аутентификацию и переадресует на, допустим, главную страницу сайта.
После первого комментария, можно дальше не наблюдать за темой.
Переадресацию, кстати, делайте на ту страницу с которой пользователь вошел (или на тут, где он нажал на ссылку «Войти»). Не делайте строгий редирект на главную.
Да, я так и делаю, разумеется. Просто не хотелось вдаваться в лишние детали.
Есть еще такое решение:

Редирект делаеться через функцию а-ля myRedir()
В функции смотрите отправлены ли залоловки (headers_sent()) - если да редирект делаеться по средствам html \ JS
Если нет - редирект через header();
Можно делать и так, но я ни разу не сталкивался со случаем, когда после обработки POST запроса (добавление комментария и в гостевую) нужно было выводить информацию, а потом редиректить.
А что мешает совместить оба варианта? На тот случай если зайдет динозавр - первый вариант не сработает - автоматически получим второй. Да и проверять на headers_sent() не придется...
То есть, сделать такой же header(), как в первом варианте плюс после него добавить текст со ссылкой на страницу, на которую переадовываем?

Проблема в том, что это даст мелькнувший текст, который пользователь не успеет прочитать — это раздражает.
Без текста, и редирект через 0 секунд. Незачем пользователю знать, что какие-то тут технические телодвижения происходят :)
Да не будет там ничего мелькать! Увидите тут промелькнувшую надпись "The document has moved here" - расскажите чем пользовались! Она там есть, но 99% браузеров увидев редирект её не показывают, а оставшийся 1% - никуда не переходит...
Текста не было, но меня и не редиректили никуда :-)
Ошибаетесь. Вас отослали с http://www.apache.org/dist на http://www.apache.org/dist/. Да, разница всего-навсего в один символ, но сам его браузер не может добавить - это делает сервер с помощью вполне полноценного редиректа... "HTTP/1.1 301 Moved Permanently" плюс вполне полноценное описание в теле документа...
Шайтан! подловил!
А вам не кажется, что динозавры скорее неподдерживают меты и JS, чем самые основы HTTP?
Именно для них там ссылка открытым текстом через <a href...
Относительно первого варианта.
Скажите в каком именно случае он не работает (желательно название браузеров или их дальнейшее поведение).
Например, Internet Explorer 6 в Windows 2003 Server просто ничего не переадресует — просто не воспринимает этот заголовок. Не пробовал, честно говоря, именно header() слать, но точно не работает, если писать мету (это ведь то же самое, нет?). И в Windows 2000 Server — тоже самое. С IE7 в 2003 уже всё нормально. Больше я нигде не встречал такой проблемы.
Нет. Не тоже самое. Так что это именно второй способ кое-где не работает.
НЛО прилетело и опубликовало эту надпись здесь
Динозавры типа Lynx 1.0. Просто показывают пустой экран. Найти их (и скомпилировать) - та ещё проблема... Но они могут оказаться на каких-нибудь хитрых мелких устройствах типа роутеров (вряд ли это кого волнует).
Вот именно, ориентироваться надо на вменяемых людей (ну или на почти вменяемых) :-)
У меня только первый вариант используется. А про второй даже не задумывался, если честно.
Я бы выбрал 2-й вариант, т.к. иногда даже ФФ2 тупит на этих редиректах и приходиться нажимать на ссылку, к тому же никто не застрахован от случаев когда выйдет новая версия популярного браузера, в которой будет баг с редиректом и некоторое время часть людей будет пялиться в пустой экран.
Если у популярного браузера баг, то это исключительно проблема разработчиков этого горе-популярного браузера.
Таки неправда.
Самый популярный в мире браузер - ИЕ - один сплошной баг, и тем не менее, это проблема именно разработчиков.
Имеются ввиду веб-разработчики, конечно же, а не создатели ИЕ.
В контексте данного топика, проблема именно у разработчиков браузера.
А если они не научат его тег понимать? ;-)
Популярность, знаете ли, для меня такой же маловажный показатель как и красный диплом. Я надеюсь мы про осла и его популярность тут не будем разговор продолжать.
Мое мнение абсолютно противоположно.
У меня никогда на 302-Location FF не тупил. Можете подробнее описать или дать ссылки, где уже описано?
Ни разу не сталкивался с такой проблемой ни в FF2, ни в Opera, ни в IE. А вероятность того, что «выйдет новая версия популярного браузера, в которой будет баг с редиректом» стремится к нулю.
Первый. Главное учитывать тонкости с отправкой заголовков. В первую очередь касается сессий. Я обычно делаю ob_start() in the beginning of everything и забываю обо всех проблемах с «Headers already sent».
Мне не очень интересно участвовать в холиворах :) Я просто говорю как я делаю. Если вы предлагаете что-то лучше, я только буду рад новому опыту :)
Надо учесть кое-какие нюансы. Бывают моменты, когда юзеру надо сообщить, что все прокатило на ура, и у него нет проблем. К примеру, при посте куда-нибудь на форум. Тогда второй вариант без вопросов. А в случаях, когда юзера не надо ни о чем оповещать, тогда первый использовать.
При посте куда-нибудь на форум гораздо правильнее выводить сообщения о проблемах, а если их нет — редиректить сразу к опубликованному посту.
На Хабре например сообщают, что я удачно разлогинился, и перебрасывают на главную. Зачем это сделано я искренне не понимаю, разве что только ради «Обязательно приходите опять».
Тут есть такой подводный камень: если у пользователя страница редиректа загрузилась не полностью, то он может нажать на F5 и отправить форму второй раз (например продублировать комментарий).
Следует хранить копию данных переданных последний раз методом POST (например).
Я, например, проверяю перед добавлением нового комментария, нет ли в базе уже такого же комментария от этого же пользователя за последние, скажем, 10 минут. Конечно, есть вероятность, что пользователь в течение 10 минут уже написал что-то вроде «Да!» или «+1», и пытается ответить так же кому-то ещё, но тогда он сам виноват :-)
Просто $_SESSION['last_post'] = $_POST;
Потом просто сравниваем. Если публикуется совершенно новый материал — хорошо, а если человек F5 нажал — система понимает это и редиректит куда следует.
В случае с header("Location: .."); это лишнее
В большинстве случаев да, но бываю досадные исключения. Когда пользователь нажмет «стоп» и попытается сабмитить форму еще раз.
Вот как раз на форумах сделано по дурацки.
То, что всё добавилось без проблем я увижу и так.
А меня одного заботит, что использование этих вещей зависит от ситуации?

Header шлёт 302 статус, т.е. «временно не тут».
В случае, когда вы переехали по новому адресу, будет правильно или отправить 301 («переехали навсегда») и тогда Location, или вообще — просто надпись «мы переехали» с ссылкой, чтобы пользователь смог узнать новый адрес.
В случае, когда пользователь сабмитил POST, т.е. какой-нибудь комментарий написал, надо отправлять статус 303, который для этого и сделан.

Если вы беспокоитесь о браузерах, которые этого не понимают, пишите
<?php
if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') header('HTTP/1.1 303 See Other');
else header('HTTP/1.0 302 Found');
header('Location: foo');
die('<a href="foo">bar</a>');

ибо те UA, которые поймут header 303, просто не будут читать output.
303 уже есть в http/1.0
А фиг его )
Всю жизнь работал в HTTP/1.0.
Ладно, не буду настаивать
Какой распространённый браузер показывает текст после 301 или 302 ? Формально да, нужно 303 выдывать (который в HTTP/1.0 уже есть), но на практике - разницы никакой.
Никакой. Это не к сравнению 301/303, а к фразе Проблема в том, что это даст мелькнувший текст, который пользователь не успеет прочитать — это раздражает.

На практике и разницы между <img src="foo" alt="[bar]"> и <IMG SRC=FOO> тоже никакой, но вы как пишете?
Обычно <img src="foo" alt="" /> или <img src="foo" alt="bar" title="" />. А разница между <img src="foo" alt="[bar]"> и <IMG SRC=FOO> на практике таки есть: "[bar]" будет в MS IE всплывать.
Ну так не пишите alt="[bar]", пишите alt="", это же только пример был. Но по сути, а не по мелочам: 303 имеет другое значение, нежели 302, и разница тут есть.

В случае 301 это вообще смешно — 301 значит «Moved Permanently, запомнить это (кэшировать)», когда 302/303 значит «пока там, обращаться по оригинальному (а не новому) адресу», так что разница очень даже живая.

ужно 303 выдывать (который в HTTP/1.0 уже есть)
Источник?

Насчёт слэша — это тема для отдельного разговора.
вроде для поисковиков лучше 301 отдавать...

header("HTTP/1.1 301 Moved Permanently");
header("location: foo);
Интересненько. Источник?
И кстати, не забывайте не копировать из интернета, а адаптировать. В данном случае необходимо использовать $_SERVER['SERVER_PROTOCOL'] , вместо HTTP/1.1, ибо протокол может быть и HTTP 1.0.
http://www.w3.org/Protocols/rfc2616/rfc2…

If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

Note: When automatically redirecting a POST request after
receiving a 301 status code, some existing HTTP/1.0 user agents
will erroneously change it into a GET request.


К 302 это тоже относится, но там всё же сказано, что для переадресации с POST на GET практически часто используется 302.
Конечно первый, вообще лень читать о том что ты сейчас будешь перенаправлен, если по логике это и должно произойти.
НЛО прилетело и опубликовало эту надпись здесь
Перенаправление как во-втором варианте, хорош для снижения нагрузки на сервер. Иногда полезно применять такой вариант, после добавления сообщения или каких-то ресурсоёмких операций: "Ваше сообщение было добавлено, через n секунд вы будете перенаправлены туда-то, если не желаете ждать нажмите сюда-то" или т.п.

Если сервак справляется с нагрузкой то второй вариант нежелателен, так как будет лишним раздражителем для пользователя.
НЛО прилетело и опубликовало эту надпись здесь
при чем тут нагрузка?
хтмл-редирект при обработке форм используется чтоб избежать повторной отправки POST при Ф5
эм... а где тут собсна снижается нагрузка на сервер о_О
Это снизит частоту ресурсоемких запросов, и как следствие суммарную загрузку сервера.
конечно первый. Где вы видели броузеры которые не поддерживают редиректы?
Вариант с meta использовал, когда нужно было кое-что протестировать. Сделал редирект страницы на саму себя и получил тысячи открытий сайтов.

Что интересно, редирект через header работает и с ajax, т.е. XMLHttpRequest тоже редиректится.
сделал на php:
header("Location: index.php");
die("not logged in");
потом пытался на javascript поймать эту строку "not logged in", чтобы соответственно обработать - нифига, получал вывод index.php
А почему он, собственно, не должен работать? :)
Ага, работает)
Например если в вконтакте в статусе понаживать быстро ентер, то вместо статуса туда подгрузится страница с текстом, что типа больше одного действия в секунду сделали :)
Смотрится забавненько так
ага, но у второго варианта тоже есть минус - вдруг в браузере пользователя не поддерживаются и гипперссылки?
*сделав умное лицо*
гиперссылки - основа веба!
*убрав умное лицо*
вряд ли, если не поддерживаются ссылки, то поддерживаются формы - и как же этот несчастный смог попасть на страницу, с которой редирект?
Основа веба протокол HTTP. А редирект одна из основ HTTP :)
ну в том то и прикол, что если у юзера редирект не работает в браузере то и ссылки наверно тоже) у него похоже блокнот вместо брузера открыт
гиперссылки - основа хтмл, а не веба. А юзер может написал плагин к блокноту, который умеет получать по http, но пока не научился показывать html.
У меня на сайте http://ubuntu.onego.ru установлен 1 вариант.

Потому, что, на мой взгляд в данном случае пользователю не важно знать, куда его переадресовывают. Тем более, это связано с текущими техническими возможностями.

Если же переадресация установлена потому, что пользователь что-то сделал неправильно или есть более простой вариант, то показать стоит. И возможно, стоит дождаться клика.
Если обобщить — посетителю не должно прийти в голову, что его куда-то перенаправляют.

Решение:
Если браузер поддерживает — перенаправлять сразу.
Если нет — показывать ссылку.
header("location: /") не всегда возможен....так что иногда приходится и location.href='/' делать
а какой вообще браузер не поддерживающий редиректы наиболее распространен?

потому что мне может быть не повезло, не знаю, но я за 10 лет ни разу такого не видел.
ну, которым пользуются _люди_
Я использую такой вариант:

%%
header ("Location: http://www.sitename.dom/page/");
exit('http://www.sitename.dom/page/');
%%

рекомендую.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории