Remembering Users in PHP: Why setcookie() and session_start() Want to Be at the Top of the Page

When a web server sends a response to a web client, most of that response is the HTML document that the browser renders into a web page on your screen: the soup of tags and text that Safari or Firefox formats into tables or changes the color or size of. But before that HTML is a section of the response that contains headers. These don’t get displayed on your screen but are commands or information from the server for the web client. The headers say things such as “this page was generated at such-and-such a time” “please don’t cache this page” or the one that’s relevant here, “please remember that the cookie named userid has the value ralph”

All of the headers in the response from the web server to the web client have to be at the beginning of the response, before the response body, which is the HTML that con­trols what the browser actually displays. Once some of the body is sent—even one line—no more headers can be sent.

Functions such as setcookie() and session_start() add headers to the response. In order for the added headers to be sent properly, they must be added before any output starts. That’s why they must be called before any print statements or any HTML appearing outside <?php ?> PHP tags.

If any output has been sent before setcookie() or session_start() is called, the PHP engine prints an error message that looks like this:

Warning: Cannot modify header information – headers already sent by

(output started at /www/htdocs/catalog.php:2)

in /www/htdocs/catalog.php on line 4

This means that line 4 of catalog.php called a function that sends a header, but some­thing was already printed by line 2 of catalog.php.

If you see the “headers already sent” error message, scrutinize your code for errant output. Make sure there are no print statements before you call setcookie() or session_start(). Check that there is nothing before the first <?php start tag in the page. Also, check that there is nothing outside the <?php and ?> tags in any included or required files—even blank lines.

An alternative to hunting down mischievous blank lines in your files is to use output buffering. This tells the PHP engine to wait to send any output until it’s finished pro­cessing the whole request. Then, it sends any headers that have been set, followed by all the regular output. To enable output buffering, set the output_buffering configu­ration directive to On in your server configuration. Web clients will have to wait a few additional milliseconds to get the page content from your server, but you’ll save megaseconds by not having to fix your code to have all output happen after calls to setcookie() or session_start().

With output buffering turned on, you can mix print statements, cookie and session functions, HTML outside of <?php and ?> tags, and regular PHP code without getting the “headers already sent” error. The program in Example 10-20 works only when output buffering is turned on. Without it, the HTML printed before the <?php start tag triggers the sending of headers, which prevents setcookie() from working properly.

Example 10-20. A program that needs output buffering to work


<head>Choose Your Site Version</head>



setcookie(‘seen_intro’, 1);


<a href=”/basic.php”>Basic</a> or

<a href=”/advanced.php”>Advanced</a>



Source: Sklar David (2016), Learning PHP: A Gentle Introduction to the Web’s Most Popular Language, O’Reilly Media; 1st edition.

Leave a Reply

Your email address will not be published. Required fields are marked *