Чтобы понять ценность написанных вами утверждений, вам необходимо иметь некоторое базовое представление о действиях функций, которые вы упоминаете. Я постараюсь сломать их здесь.
Давайте начнем с session_start()
и header()
вызовов:
Первая функция делает именно то, что подразумевает название; начинается сессия
Из-за природы HTTP-протокола без сохранения состояния необходим некоторый механизм, который может запоминать состояние между запросами страниц. Это может быть достигнуто с помощью сеансов. Хотя в первые дни PHP сеансы иногда распространялись путем передачи идентификатора сеанса в ссылках (someurl?sessionId=someSessionHash
), в настоящее время это считается плохой практикой.
В настоящее время сессии отслеживаются преимущественно с помощью файлов cookie (в первые дни, когда они также широко использовались, не поймите меня неправильно). Этот cookie-файл сеанса (который, вопреки распространенному мнению, является не чем иным, как обычным cookie-файлом, содержащим только идентификатор сеанса, который (обычно) просто истекает после закрытия браузера), отправляется в браузер с каждым последующим запросом страницы , И вот где подвох: cookie отправляется как заголовок ответа (т.е. перед фактическим телом), например так:
// I've left out a lot of other headers for brevity
HTTP/1.x 200 OK
Date: Sun, 31 Jan 2010 09:37:35 GMT
Cookie: SESSION=DRwHHwAAACpes38Ql6LlhGr2t70df // here is your Cookie header
// after all response headers come the actual content:
// the response body, for instance:
<html>
<head>
</head>
<body>
</body>
</html>
Теперь, поскольку заголовки ответа должны отправляться перед телом ответа, вам необходимо вызвать session_start()
и header()
перед выводом любого содержимого тела. И вот почему: если вы выводите какое-либо содержимое тела ответа (может быть что-то такое же простое, как символ пробела) перед вызовом session_start()
или header()
, PHP автоматически выведет заголовки ответа. Это связано с тем, что в ответе HTTP должны быть отправлены заголовки ответа перед телом ответа. И именно это часто приводит к печально известному предупреждению Warning: headers already sent
в PHP. Другими словами; После того как PHP отправил заголовки, потому что он также должен был отправлять данные тела, он больше не может добавлять заголовки.
Итак, теперь, когда вы поняли это по протоколу HTTP, вы можете предпринять некоторые измерения, чтобы этого не произошло. И вот тут мы подходим к следующим функциям:
ob_start
, ob_flush
и т.д ...:
В настройках по умолчанию PHP обычно выводит все сразу. Поэтому, если вы выводите какое-либо содержимое тела ответа, заголовки автоматически отправляются первыми.
Но PHP предлагает механизмы буферизации вывода. Это семейство функций ob_*
. С ob_start
вы говорите PHP начать буферизацию. И с ob_flush
вы говорите PHP очистить буфер; другими словами, выведите текущее содержимое буфера на стандартный вывод.
С помощью этих механизмов буферизации вы все равно можете добавлять заголовки к ответу после того, как вы получили выходные данные тела, потому что вы еще не отправили данные тела, вы просто буферизировали их, чтобы потом вывести с вызовом ob_flush
или ob_end_flush
и что у тебя.
Имейте в виду, однако, что использование ob_*
функций чаще, чем запах кода. Другими словами (и именно поэтому важно делать определенные вещи сверху), он затем используется, чтобы восполнить плохой дизайн. Кто-то забыл правильно настроить порядок своих операций и прибегает к буферизации вывода, чтобы обойти эту драму header
и session
.
Сказав все это, вы легко поймете, почему вывод html и / или другого основного содержимого должен быть последним. Кроме того, я настоятельно рекомендую вам в любом случае отделить код PHP от кода вывода. Потому что это намного легче читать и понимать. И хороший способ начать это, когда фактический html идет после основного <?php ?>
блока кода. Но есть и другие способы, которые выходят за рамки этих вопросов.
Затем, наконец, о include
и require
вызовах. Иметь их в верхней части ваших php-файлов обычно просто для разъяснения. Он хорошо хранит эти звонки в одном месте. Но имейте в виду, что если один из этих файлов выведет что-либо перед вызовом session_start()
или header()
без использования буферизации вывода, вы снова облажаетесь.