PHPのお勉強!

PHP TOP

header

(PHP 4, PHP 5, PHP 7, PHP 8)

header生の HTTP ヘッダを送信する

説明

header(string $header, bool $replace = true, int $response_code = 0): void

header() は、生の HTTP ヘッダを送信するために使用されます。 HTTP ヘッダについての詳細な情報は » HTTP/1.1 仕様 を参照ください。

覚えておいて頂きたいのは、header() 関数は、 通常の HTML タグまたは PHP からの出力にかかわらず、すべての実際の 出力の前にコールする必要があることです。 頻出するエラーとして、include または require 関数、他のファイルをアクセスする関数に 空白または空行があり、header() の前に出力が 行われてしまうというものがあります。同じ問題は、単一の PHP/HTML ファイルを使用している場合でも存在します。

<html>
<?php
/* これはエラーとなります。この上に出力があることに注目してください。
* それはheader()のコールより前であるということになります */
header('Location: http://www.example.com/');
exit;
?>

パラメータ

header

ヘッダ文字列。

特殊な header コールが 2 種類あります。最初のものは、 文字列 "HTTP/" から始まる全てのヘッダ (大文字・小文字は区別されません) です。 このヘッダは、送信する HTTP ステータスコードを示すために使用されます。 例えば、存在しないファイルへのリクエストを処理するためにある PHP スクリプトを使用するよう (ErrorDocument ディレクティブにより) Apache を設定する場合、 そのスクリプトが正しいステータスコードを返すようにする必要があります。

<?php
// この例は、"HTTP/" から始まる特別な場合を示しています。
// これより良い、典型的な使い方として、以下があげられます:
// 1. header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found");
// (HTTP/1.0 を使いながら、httpステータスメッセージを上書きする)
// 2. http_response_code(404); (デフォルトのメッセージを使う)
header("HTTP/1.1 404 Not Found");
?>

2 番目の特別なヘッダは、"Location:" ヘッダです。このヘッダがブラウザに返されるだけではなく、 ブラウザに REDIRECT (302) ステータスコードを返します (2013xx ステータスコードが既に送信されていない場合にのみ)。

<?php
header
("Location: http://www.example.com/"); /* ブラウザをリダイレクトします */

/* リダイレクトする際に、これ以降のコードが実行されないことを確認してください */
exit;
?>

replace

オプションのパラメータ replace は、ヘッダが 前に送信された類似のヘッダを置換するか、または、同じ形式の二番目の ヘッダを追加するかどうかを指定します。デフォルトでは、この関数は 置換を行ないますが、二番目の引数に false を指定すると、同じ型の 複数のヘッダを強制的に生成します。例えば、

<?php
header
('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM', false);
?>

response_code

HTTP レスポンスコードを強制的に指定の値にします。このパラメータが意味をなすのは header が空文字列でないときだけであることに注意しましょう。

戻り値

値を返しません。

エラー / 例外

ヘッダを予定通りに送信できなかった場合、 header() 関数は E_WARNING レベルの警告を発生させます。

例1 ダウンロードダイアログ

PDF ファイルを生成した場合など、 それをダウンロードするかの確認ダイアログを表示させたいことがあるでしょう。 そんな場合は、» Content-Disposition ヘッダを使用してファイル名を指定すると、ブラウザ側でダイアログを表示させることができます。

<?php
// PDFを出力します
header('Content-Type: application/pdf');

// downloaded.pdf という名前で保存させます
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// もとの PDF ソースは original.pdf です
readfile('original.pdf');
?>

例2 キャッシュディレクティブ

PHP スクリプトはしばしば動的に HTML を生成するため、クライアント ブラウザやサーバーおよびクライアントブラウザの間でプロキシがキャッシュを 行ったりするべきではありません。多くのプロキシとクライアントでは、 以下のコードにより強制的にキャッシュを無効にできます。

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去の日付
?>

注意:

上記のヘッダを全て出力しなかったとしてもページのキャッシュが 行われない場合があることに気付くかもしれません。デフォルトの ブラウザのキャッシュの動作をユーザーが変更できる手段はいくつもあります。 上記のヘッダを送信することにより、スクリプトの出力がキャッシュされる 可能性がある設定を上書きするべきです。

さらに、session_cache_limiter() および 設定 session.cache_limiter を用いると、 セッションが使用された際にキャッシュ関係の正しいヘッダを 自動的に生成させることもできます。

例3 クッキーを設定する

setcookie() は、クッキーを設定する便利な方法を提供します。 setcookie() がサポートしていない属性をクッキーに設定する方法として、 header() が使えます。

たとえば、以下のコードは Partitioned 属性を含むクッキーを設定します。

<?php
header
('Set-Cookie: name=value; Secure; Path=/; SameSite=None; Partitioned;');
?>

注意

注意:

ヘッダにアクセスできたりヘッダを出力したりするのは、 それに対応した SAPI を使っている場合のみです。

注意:

出力のバッファリングを使用してこの問題を回避することができます。 この場合、ブラウザへの出力が送信するまでサーバーに 全てバッファリングされるオーバーヘッドがあります。出力バッファリングは、 ob_start()ob_end_flush() をスクリプトでコールするか php.ini またはサーバー設定ファイルの設定ディレクティブ output_buffering を設定することにより 行うことが可能です。

注意:

実際に header() が最初にコールされたか どうかにかかわらず、HTTP ステータスヘッダ行は クライアントに対し常に最初に送信されます。 HTTP ヘッダが既に送信されていない限り、 header() をコールすることでステータスは 常に上書きされます。

注意:

最近のクライアントの大半は » Location: への引数として相対 URI も受け付けますが、 古いクライアントの中にはスキームとホスト名そして絶対パスを含む絶対 URL しか受け付けないものもあります。 通常は、相対 URI から絶対 URI を作成するためには $_SERVER['HTTP_HOST']$_SERVER['PHP_SELF'] および dirname() を使用できます。

<?php
/* カレントディレクトリの別のページにリダイレクトします */
$host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
$extra = 'mypage.php';
header("Location: http://$host$uri/$extra");
exit;
?>

注意:

session.use_trans_sid が有効であったとしても、セッション ID が Location ヘッダとともに 渡されることはありません。SID 定数を使用して 手動で渡す必要があります。

参考

add a note

User Contributed Notes 26 notes

up
247
mjt at jpeto dot net
15 years ago
I strongly recommend, that you use

header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");

instead of

header("HTTP/1.1 404 Not Found");

I had big troubles with an Apache/2.0.59 (Unix) answering in HTTP/1.0 while I (accidentially) added a "HTTP/1.1 200 Ok" - Header.

Most of the pages were displayed correct, but on some of them apache added weird content to it:

A 4-digits HexCode on top of the page (before any output of my php script), seems to be some kind of checksum, because it changes from page to page and browser to browser. (same code for same page and browser)

"0" at the bottom of the page (after the complete output of my php script)

It took me quite a while to find out about the wrong protocol in the HTTP-header.
up
169
Marcel G
14 years ago
Several times this one is asked on the net but an answer could not be found in the docs on php.net ...

If you want to redirect an user and tell him he will be redirected, e. g. "You will be redirected in about 5 secs. If not, click here." you cannot use header( 'Location: ...' ) as you can't sent any output before the headers are sent.

So, either you have to use the HTML meta refresh thingy or you use the following:

<?php
header
( "refresh:5;url=wherever.php" );
echo
'You\'ll be redirected in about 5 secs. If not, click <a href="wherever.php">here</a>.';
?>

Hth someone
up
91
Dylan at WeDefy dot com
17 years ago
A quick way to make redirects permanent or temporary is to make use of the $http_response_code parameter in header().

<?php
// 301 Moved Permanently
header("Location: /foo.php",TRUE,301);

// 302 Found
header("Location: /foo.php",TRUE,302);
header("Location: /foo.php");

// 303 See Other
header("Location: /foo.php",TRUE,303);

// 307 Temporary Redirect
header("Location: /foo.php",TRUE,307);
?>

The HTTP status code changes the way browsers and robots handle redirects, so if you are using header(Location:) it's a good idea to set the status code at the same time. Browsers typically re-request a 307 page every time, cache a 302 page for the session, and cache a 301 page for longer, or even indefinitely. Search engines typically transfer "page rank" to the new location for 301 redirects, but not for 302, 303 or 307. If the status code is not specified, header('Location:') defaults to 302.
up
38
mandor at mandor dot net
18 years ago
When using PHP to output an image, it won't be cached by the client so if you don't want them to download the image each time they reload the page, you will need to emulate part of the HTTP protocol.

Here's how:

<?php

// Test image.
$fn = '/test/foo.png';

// Getting headers sent by the client.
$headers = apache_request_headers();

// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
header('Content-Length: '.filesize($fn));
header('Content-Type: image/png');
print
file_get_contents($fn);
}

?>

That way foo.png will be properly cached by the client and you'll save bandwith. :)
up
4
Emmanuel Chazard
1 year ago
If you use header() to allow the user to download a file, it's very important to check the encoding of the script itself. Your script should be encoded in UTF-8, but definitely not in UTF-8-BOM! The presence of BOM will alter the file received by the user. Let the following script:

<?php

$content
= file_get_contents('test_download.png') ;
$name = 'test.png' ;
$size = strlen($content) ;

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: 0');
header('Content-Disposition: attachment; filename="'.$name.'"');
header('Content-Length: ' . $size);
header('Pragma: public');

echo
$content ;

?>

Irrespectively from the encoding of test_download.png, when this PHP script is encoded in UTF-8-BOM, the content received by the user is different:
- a ZWNBSP byte (U+FEFF) is added to the beginning of the file
- the file content is truncated!!!
If it's a binary file (e.g. image, proprietary format), the file will become unreadable.
up
10
php at ober-mail dot de
5 years ago
Since PHP 5.4, the function `http_​response_​code()` can be used to set the response code instead of using the `header()` function, which requires to also set the correct protocol version (which can lead to problems, as seen in other comments).
up
29
bebertjean at yahoo dot fr
16 years ago
If using the 'header' function for the downloading of files, especially if you're passing the filename as a variable, remember to surround the filename with double quotes, otherwise you'll have problems in Firefox as soon as there's a space in the filename.

So instead of typing:

<?php
header
("Content-Disposition: attachment; filename=" . basename($filename));
?>

you should type:

<?php
header
("Content-Disposition: attachment; filename=\"" . basename($filename) . "\"");
?>

If you don't do this then when the user clicks on the link for a file named "Example file with spaces.txt", then Firefox's Save As dialog box will give it the name "Example", and it will have no extension.

See the page called "Filenames_with_spaces_are_truncated_upon_download" at
http://kb.mozillazine.org/ for more information. (Sorry, the site won't let me post such a long link...)
up
3
David Spector
3 years ago
Please note that there is no error checking for the header command, either in PHP, browsers, or Web Developer Tools.

If you use something like "header('text/javascript');" to set the MIME type for PHP response text (such as for echoed or Included data), you will get an undiagnosed failure.

The proper MIME-setting function is "header('Content-type: text/javascript');".