cannot start session when headers already sent in php

Опасная ошибка: headers already sent

Сегодня я хочу рассказать вам об одной очень популярной и загадочной ошибке. Наверняка, многие из вас во время отладки своих программ сталкивались со следующим сообщением: headers already sent. Переводится на русский язык данная запись как «заголовки уже отправлены».

Чтобы понять суть этой ошибки, давайте вспомним структуру http-пакетов:

Т.е. говоря headers already sent программа ругает нас, за то, что мы уже где-то начали формировать тело сообщения (3-ю часть http-пакета), но снова хотим отправить заголовки (2-ую часть).

Приведу пару примеров: лёгкий и адский – с точки зрения возможности заметить ошибку.

Пример 1 – лёгкий.

Будет выведена ошибка:

Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent

Мы не имели права вызывать функцию session_start(), после использования оператора echo. Такую ошибку исправить несложно – уберите отладочное echo.

Пример 2 – жуткий.

Представим, что у нас есть абстрактный файл модели model.php, который мы подключаем на нужную нам страничку a.php.

Но неожиданно денвер снова говорит:

Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent

Как? Почему? Ведь мы ещё не начинали формирования тела сообщения! И вот здесь, прежде чем удастся найти ошибку, можно расколотить компьютер или удалить локальный сервер. А всё приключилось потому, что мы нарушили золотое правило – никогда не закрывайте блок php, если в конкретном файле после него не идёт html.

Давайте взглянем на файл модели:

Также важно понимать, что речь идёт не только о конкретной функции session_start, но и обо всех остальных, которые выполняют отправку заголовков, например: setcookie, header итд.

И об ошибке headers already sent Вы забудете!

Источник

Что означает предупреждение «headers already sent»

В ответ на этот запрос веб-сервер запускает выполнение нашего php-скрипта, к которому обращается браузер. И веб-сервер отправляет браузеру результат работы скрипта. но перед этим он отправит свои заголовки ответа.

Как вы видите, заголовки идут вначале, а после одной пустой строки начинается тело самого html, который мы генерируем с помощью php-скрипта.

И вот мы подошли к основной сути. когда PHP приказывает веб-серверу начать отправлять само содержимое брузеру, то веб-серверу не остаётся ничего, кроме как отправить вначале все заголовки, которые имеются у него на текущий момент. Поэтому после этого PHP уже не сможет изменить эти заголовки.
Функция header() изменяет любой заголовок. Функция setcookie() добавляет куки к заголовку Set-Cookie, поэтому тоже не может работать после отправки заголовков. session_start() добавляет куки с идентификатором сессии (как в примере выше).

Я вижу 2 пути решения это проблемы:
1. Включить в php.ini

На вашем компьютере это должно помочь. Но если вы позже закачаете свой сайт на хостинг, то у вас не будет уверенности, что там включен этот буфер.
2. Запретить текстовому редактору сохранять BOM. Но тут уже всё зависит от возможностей текстового редактора, который вы используете. Например, я пользуюсь Notepad++. там можно открыть меню «Кодировки» и выбрать «Преобразовать в UTF-8 без BOM».

Если вы уверены, что BOM не используется, значит где-то перед функциями header(), setcookie() и т.п. вы сами отправляете данные пользователю. Возможно, перед открытием тега 57

Читайте также:  что необходимо для новорожденного в первые месяцы жизни список осень

Источник

‘Cannot start session when headers already sent’ on run Unit Test #476

Comments

eliasjtg commented Nov 6, 2019

Describe the bug
On run unit test this fails with the log:

To Reproduce
Steps to reproduce the behavior:

Install with composer require pragmarx/tracker

Add the service provider to app/config/app.php:
PragmaRX\Tracker\Vendor\Laravel\ServiceProvider::class

Add the alias to the facade on app/config/app.php:
‘Tracker’ => ‘PragmaRX\Tracker\Vendor\Laravel\Facade’

Enable the Middleware in app/config/tracker.php :
‘use_middleware’ => true,

Add the Middleware to Laravel Kernel:
\PragmaRX\Tracker\Vendor\Laravel\Middlewares\Tracker::class,

Enable Tracker in tracker.php:
‘enabled’ => true,

Publish the migration:
php artisan tracker:tables

Migrate:
php artisan migrate

Enable configurations:
`
‘cache_enabled’ => true,
‘log_enabled’ => true,
‘log_user_agents’ => true,
‘log_devices’ => true,
‘log_referers’ => true,
‘log_paths’ => true,
‘log_routes’ => true,
‘log_exceptions’ => true,

Expected behavior
Tests run normally

Screenshots
Gitlab CI

System

Additional context
PHP 7.3.7
Laravel 6
PHPUnit 8.4.2

The text was updated successfully, but these errors were encountered:

We are unable to convert the task to an issue at this time. Please try again.

The issue was successfully created but we are unable to update the comment at this time.

eliasjtg commented Nov 6, 2019

One solution is change PragmaRX\Support\PhpSession:27 :

eliasjtg commented Nov 6, 2019

One solution is change PragmaRX\Support\PhpSession:27 :

I dont know if this cause it, but if change config/tracker.php :

The test starts run but trow this exception:

Источник

Warning: session_start(): Cannot start session when headers already sent in (. ) on line 2 [duplicate]

Why does it error Warning: session_start(): Cannot start session when headers already sent in (. ) on line 2? I’m trying to test session stuff with my current site, so I can make it so I send information that is preset to another web page, but it gives me this error before I even log in.

2 Answers 2

Fix for this will be removing the whitespace before as that will be output too.

This usually means that some output from your PHP script has already been prepared (or sent) to the client for the current request.

Headers are used in a lot of programmatic communications and they are a way to prepare the receiver for whatever is about to happen. They usually contain stuff like content type, how many bytes the incoming data is and other meta data.

So the solution is to figure out where your php stack is sending out headers before you call that session_start() function. Be aware that any printed white space counts! That little factoid lets us look at your code again and see that there is a tab before your opening tag. That’s whitespace, which initiates the data send which means your headers are already on their way to the client by the time you run any php at all!

Читайте также:  Что такое примеры с переходом через разряд

Источник

How to fix «Headers already sent» error in PHP

When running my script, I am getting several errors like this:

The lines mentioned in the error messages contain header() and setcookie() calls.

What could be the reason for this? And how to fix it?

11 Answers 11

No output before sending headers!

Functions that send/modify HTTP headers must be invoked before any output is made. summary ⇊ Otherwise the call fails:

Some functions modifying the HTTP header are:

Why does it happen?

To understand why headers must be sent before output it’s necessary to look at a typical HTTP response. PHP scripts mainly generate HTML content, but also pass a set of HTTP/CGI headers to the webserver:

The page/output always follows the headers. PHP has to pass the headers to the webserver first. It can only do that once. After the double linebreak it can nevermore amend them.

How can you find out where the premature output occurred?

The header() warning contains all relevant information to locate the problem cause:

Here «line 100» refers to the script where the header() invocation failed.

Print, echo

Intentional output from print and echo statements will terminate the opportunity to send HTTP headers. The application flow must be restructured to avoid that. Use functions and templating schemes. Ensure header() calls occur before messages are written out.

Functions that produce output include

among others and user-defined functions.

Raw HTML areas

Use a templating scheme to separate processing from output logic.

Whitespace before for «script.php line 1» warnings

Similarly it can occur for appended scripts or script sections:

PHP actually eats up a single linebreak after close tags. But it won’t compensate multiple newlines or tabs or spaces shifted into such gaps.

UTF-8 BOM

In particular graphical editors and Java-based IDEs are oblivious to its presence. They don’t visualize it (obliged by the Unicode standard). Most programmer and console editors however do:

There it’s easy to recognize the problem early on. Other editors may identify its presence in a file/settings menu (Notepad++ on Windows can identify and remedy the problem), Another option to inspect the BOMs presence is resorting to an hexeditor. On *nix systems hexdump is usually available, if not a graphical variant which simplifies auditing these and other issues:

An easy fix is to set the text editor to save files as «UTF-8 (no BOM)» or similar to such nomenclature. Often newcomers otherwise resort to creating new files and just copy&pasting the previous code back in.

Correction utilities

There are also automated tools to examine and rewrite text files ( sed / awk or recode ). For PHP specifically there’s the phptags tag tidier. It rewrites close and open tags into long and short forms, but also easily fixes leading and trailing whitespace, Unicode and UTF-x BOM issues:

Читайте также:  минимальная заработная плата что входит в расчет

It’s safe to use on a whole include or project directory.

Error source mentioned as «Unknown on line 0»

It’s typically a PHP extension or php.ini setting if no error source is concretized.

Preceding error messages

If another PHP statement or expression causes a warning message or notice being printed out, that also counts as premature output.

No error message

Or set_error_handler(«var_dump»); if all else fails.

Speaking of redirect headers, you should often use an idiom like this for final code paths:

Preferably even a utility function, which prints a user message in case of header() failures.

Output buffering as a workaround

PHPs output buffering is a workaround to alleviate this issue. It often works reliably, but shouldn’t substitute for proper application structuring and separating output from control logic. Its actual purpose is minimizing chunked transfers to the webserver.

It can likewise be engaged with a call to ob_start(); atop the invocation script. Which however is less reliable for multiple reasons:

Even if starts the first script, whitespace or a BOM might get shuffled before, rendering it ineffective.

It can conceal whitespace for HTML output. But as soon as the application logic attempts to send binary content (a generated image for example), the buffered extraneous output becomes a problem. (Necessitating ob_clean() as a further workaround.)

The buffer is limited in size, and can easily overrun when left to defaults. And that’s not a rare occurrence either, difficult to track down when it happens.

See also the basic usage example in the manual, and for more pros and cons:

But it worked on the other server!?

If you didn’t get the headers warning before, then the output buffering php.ini setting has changed. It’s likely unconfigured on the current/new server.

Checking with headers_sent()

You can always use headers_sent() to probe if it’s still possible to. send headers. Which is useful to conditionally print info or apply other fallback logic.

Useful fallback workarounds are:

HTML tag

If your application is structurally hard to fix, then an easy (but somewhat unprofessional) way to allow redirects is injecting a HTML tag. A redirect can be achieved with:

Or with a short delay:

This leads to non-valid HTML when utilized past the section. Most browsers still accept it.

JavaScript redirect

As alternative a JavaScript redirect can be used for page redirects:

While this is often more HTML compliant than the workaround, it incurs a reliance on JavaScript-capable clients.

Both approaches however make acceptable fallbacks when genuine HTTP header() calls fail. Ideally you’d always combine this with a user-friendly message and clickable link as last resort. (Which for instance is what the http_redirect() PECL extension does.)

Why setcookie() and session_start() are also affected

Both setcookie() and session_start() need to send a Set-Cookie: HTTP header. The same conditions therefore apply, and similar error messages will be generated for premature output situations.

Источник

Образовательный портал