「PHPでページのリダイレクトを実装したい」「レスポンス形式を指定したい」そんなときに使われるのがheader関数です。しかし、header関数は正しく使わないとエラーが出たり、意図しない動作を引き起こすことがあります。
本記事では、header関数の基本構文からリダイレクト処理、Content-Typeの設定方法、よくあるエラーの原因と解決策、セキュリティ対策まで徹底解説します。ぜひ参考にしてください。
目次
1.PHPのheader関数とは?役割と基本構文
Web開発では、ページのリダイレクトやデータ形式の指定など、HTTPレスポンスを制御したい場面が出てきます。PHPではheader関数を使うことで対応可能です。ここでは、header関数の役割と基本構文、HTTPヘッダーの仕組みについて解説します。
PHPのheader関数とは?HTTPレスポンスヘッダーとは?
header関数はHTTPレスポンスヘッダーを出力するための関数です。HTTPレスポンスヘッダーとは、WebサーバーがブラウザなどのWebクライアントに送る指示情報のことで、Webページをどう扱うかを決める重要な情報の集まりです。
header関数を使うと「別ページへ遷移してほしい」とか「このコンテンツはJSON形式だ」などの情報や指定を伝えることができます。WebブラウザやAPIクライアントは、PHPのコードから送信されたレスポンスヘッダーに従い動作を決定します。つまりHTTPレスポンスヘッダーは、WebページやAPIの正しい動作に必要不可欠な存在です。
PHPではヘッダー情報をheader関数ひとつで制御できるのです。
Content-Type:データの種類(HTML、JSON、CSSなど)
Location:転送先URLの指定
Cache-Control:キャッシュの有効期限・無効化や保存ルールの設定
Content-Length:レスポンス本文のサイズ(バイト数)
Set-Cookie:ブラウザに送るCookieの指示
なお、HTTPヘッダーはレスポンスの最初に送信される情報であり、HTMLや文字列などが先に出力されるとヘッダーの送信ができなくなるため、header関数は出力処理の前に記述する必要があるので注意してください。
PHPにおけるheader関数の基本的な使い方
PHPにおけるhttpヘッダー設定の方法
header関数の書き方は非常にシンプルです。
header("ヘッダー名: 値"); |
たとえば、ページを別URLへ転送するには次のように記述しましょう。
コード例
header("Location: https://example.com/thanks"); exit; |
このコード例では、Locationヘッダーで遷移先を指定し、exitでスクリプトの処理を終了させています。header関数の直後にexitを書くことで、不要な処理の実行を防げます。
また、レスポンスの形式をJSONに指定したい場合は、次のように書きましょう。
header("Content-Type: application/json; charset=utf-8"); |
2.PHPheader('Location')を使ってリダイレクトする方法
フォーム送信後にサンクスページへ遷移させたいときや、アクセス制限のあるページからログイン画面に戻したいときなど、PHPでは header関数に(’Location')を設定してリダイレクト処理をさせましょう。
ここでは、Locationヘッダーによるリダイレクトの基本と、ステータスコードごとの使い分け、リダイレクトがうまくいかないときの原因と解決策について解説します。
Locationヘッダーでリダイレクト処理を行う基本の方法
PHPでリダイレクト処理をするには、HTTPレスポンスヘッダーに「Location」と「リダイレクト先を指定すると実装可能です。
コード例
header("Location: https://example.com/thanks"); exit; |
このコード例では、https://example.com/thanksにリダイレクトされます。直後にexitを書く理由は他のヘッダーと同様で、リダイレクト後に続く処理を止め不要な出力を防ぐためです。
リダイレクト先として、URLでも相対パスでも設定できますが、意図しない動作を防ぐために、絶対的なパスであるURLを指定することをおすすめします。
相対パスで指定するコード例
header("Location: /login.php"); exit; |
ステータスコード別のリダイレクトの違い
Locationヘッダーを使ったリダイレクトでは、HTTPステータスコードを明示的に指定することで、検索エンジンやクライアントに意図を伝えることができます。
ステータスコードを指定してリダイレクト情報を送信設定するためには、次のコード例を参考にしてください。
header("HTTP/1.1 301 Moved Permanently"); header("Location: /new-page.php"); exit; |
なお、ステータスコードの意味と主な用途は下表の通りです。
ステータスコード | 意味 | 主な用途 |
---|---|---|
301 | Moved Permanently (恒久的な移動) | SEO対策で旧URLから新URLへ転送する場合 |
302 | Found | リクエストしたリソースが一時的に移動されている場合 |
303 | See Other (他を参照せよ) | フォーム送信後に結果ページへ誘導する場合 |
307 | Temporary Redirect | POSTデータを保持したままリダイレクトさせたい場合 |
SEO目的の場合は、301リダイレクトを明示的に指定しましょう。何も指定しない場合、PHPは302を自動的に使用します。303や307の使い方はAPIやフォーム送信時の挙動に影響するため、正確に使い分けましょう。
PHPのheaderでlocation先に飛ばないときの原因と対応方法
header('Location:URL')を使ったのにlocation先に遷移しないことがあります。原因の多くは、ヘッダー送信のルール違反やコード上のミスです。よくある原因と対応方法を紹介します
出力処理より前にheaderを記述していない
echoやHTMLタグの出力が先にあると、すでにレスポンスの一部が送信されているため、header関数が機能しません。
エラーになるコード例
echo "処理を開始します。"; header("Location: /login.php"); |
対策としてはheader関数は必ず、出力処理より前に記述しましょう。
header("Location: /login.php"); exit; |
exitを記述していない
header関数でLocationを指定したあとにexitを書いていない場合、後続の処理が実行され、結果的にページが動作しないことがあります。ぜひheaderの直後には「exit;」を書いて、リダイレクト以降の処理を止めてください。
関連記事
PHPでできること・できないことを解説!初心者でも作れるものや学習方法も紹介
3.PHPのheaderで値を渡す方法と注意点
PHPでリダイレクト処理を行うときに、遷移先のページにデータを渡したいケースがありませんか?。たとえば「ログイン成功後にユーザー名を表示したい」とか「問い合わせ完了ページにステータスを表示したい」といった場面です。このような場面で、headerを使って値を渡せば対応可能です
ここではPHPのheaderで値を渡す方法とコード例、注意点についてわかりやすく解説します。
URLパラメータで値を渡す
もっとも手軽な方法は、リダイレクト先のURLにパラメータを付与する方法です。
GETメソッドの形式で値を渡すことで、次のページで$_GETを使って受け取れます。
header("Location: /thanks.php?status=success&user=tanaka"); exit; |
上記のようにクエリ文字列を含めてURLを指定すれば、thanks.php側では次のコード例のように値を取得可能です。
$status = $_GET['status'] ?? ''; $user = $_GET['user'] ?? ''; |
URLに値が表示されるためデバッグしやすい点がメリットです。一方で、パスワードや個人情報など、機密性の高い情報を渡したいときには対応できません。絶対に含めないよう注意してください。
また、パラメータに日本語を含める場合には、urlencode関数を使ってエンコードする必要があります。
$name = urlencode("山田太郎"); header("Location: /profile.php?name={$name}"); exit; |
セッションを利用する
URLパラメータとGETパラメータで渡す以外に、セッションやCookieを使って値を引き継ぐ方法もあります。ユーザーごとに一時的な値を保持したいときや、URLに値を含めたくない場合に有効です。
Cookieはクライアントのブラウザに情報を保存するため、データの信頼性や改ざんリスクがありますのでセッションの使用をおすすめします。
セッションを使う方法
まず、セッションを開始し、値を格納しましょう。
session_start(); $_SESSION['message'] = 'お問い合わせありがとうございました。'; header("Location: /thanks.php"); exit; |
遷移先のページでは、同じくsession_start()を記述してから値を読み出します。
session_start(); $message = $_SESSION['message'] ?? ''; |
セッションはサーバー側に情報を保存する仕組みのため、URLに情報が露出せず、安全性に優れています。
Cookieを使う方法
setcookie("promo", "spring_sale", time() + 3600); header("Location: /campaign.php"); exit; |
セキュリティ対策としてリダイレクト先制御や値の検証をする
header関数で値を渡す際は、不正なアクセスやリダイレクトによるセキュリティリスクにも注意しなければなりません。特に外部から渡されたURLにそのままリダイレクトしてはいけません。詳しくは9章をご覧ください。
なおGETやPOSTの値については、filter_inputやfilter_varなどを使って、適切に値の検証・バリデーションチェックを行うのもおすすめです。
関連記事
PHPプログラミングとは?将来性や実践で活用できるコード例など初心者にわかりやすく解説
4.PHPでheaderを使う際にはcontent-typeを使いましょう
Webアプリケーションでは、ブラウザやAPIクライアントにレスポンスの形式を正確に伝える必要があり、Content-Typeヘッダーが使われます。PHPのheader関数を使えば、HTML、JSON、CSVなど、さまざまなレスポンス形式を明示的に指定可能です。
ここではContent-Typeの指定方法や使用場面、レスポンス制御の考え方を解説します。
PHPでheaderに設定するContent-Typeとは?
Content-Typeは、HTTPレスポンスの中でレスポンスのメディアタイプ(MIMEタイプ)を示すヘッダー項目です。たとえば、「このレスポンスはHTMLですよ」と伝えれば、ブラウザはそのまま表示を始めます。一方で「これはJSON形式です」と伝えれば、クライアントはそのまま処理するか、JSONとして変換します。
Content-Typeのなかでよく使われるものを紹介しましょう。
用途 | Content-Type |
---|---|
HTMLページ | text/html; charset=utf-8 |
プレーンテキスト | text/plain; charset=utf-8 |
CSSスタイル | text/css |
JavaScript | application/javascript |
JSONデータ | application/json |
XMLデータ | application/xml |
CSVファイル | text/csv |
PNG画像 | image/png |
なおContent-Typeを使う場合には、文字コードの誤認識を防ぐために「charset=utf-8」など明示することをおすすめします。
PHPでheaderにContent-Typeを指定する方法
実際にPHPでContent-Typeを設定するには、header関数を使って次のコード例のように書きましょう。
HTMLの場合
header("Content-Type: text/html; charset=utf-8"); |
JSONの場合
header("Content-Type: application/json; charset=utf-8"); echo json_encode(['status' => 'ok']); exit; |
APIレスポンスやJavaScriptとの連携では、JSONを返すことが多いでしょう。このように明示的に書くことで、JavaScript側ではJSONとして正しく読み取ることができます。
CSVファイルの場合
header("Content-Type: text/csv; charset=utf-8"); header("Content-Disposition: attachment; filename=\"data.csv\""); |
CSV形式のデータをダウンロードさせるには、Content-Typeとあわせてファイル名を設定しましょう。このコード例ではCSVファイルとして自動的にダウンロードが開始されます。
ファイルダウンロード時のContent-Dispositionと併用する
ファイルをブラウザで直接表示させず、強制的にダウンロードさせたい場合は、「Content-Disposition: attachment」を使ってください。Content-TypeとContent-Dispositionを組み合わせることが基本です。
画像をダウンロードさせる場合
header("Content-Type: image/png"); header("Content-Disposition: attachment; filename=\"logo.png\""); readfile("images/logo.png"); exit; |
このコード例では画像ファイルがブラウザに表示されるのではなく、ダウンロード処理が始まります。
なお、ファイルが存在しない場合は、readfileが失敗するため、事前に存在確認することをおすすめします。
if (file_exists("images/logo.png")) { readfile("images/logo.png"); } else { header("HTTP/1.1 404 Not Found"); echo "ファイルが見つかりません。"; } |
関連記事
【2025年版4月時点】PHP最新バージョン8.4と8系統のインストール・確認方法と安定版の選び方を解説
5.PHPにおけるhttpヘッダー設定の実践例
ここでは、実務でよく使われるhttpレスポンスヘッダーの設定方法について紹介します。
キャッシュを完全に無効化する・活用する
キャッシュを完全に無効化したい場合は次のコード例のように設定します。
header("Cache-Control: no-store, no-cache, must-revalidate"); header("Expires: 0"); |
一方、CSSや画像のようにキャッシュを積極的に活用したい場合は、max-ageで保存期間を指定してください。
header("Cache-Control: max-age=99999"); |
ExpiresはHTTP/1.0向けの設定であり、Cache-Controlが優先されるため、併用するとより確実です。
複数のヘッダーを送る
複雑なレスポンスを制御したいときは、複数のヘッダーを組み合わせて使用することが可能です。headerは複数回呼び出すことで複数のヘッダーを送信できます。1行にまとめる必要はありません。
header("Content-Type: application/pdf"); header("Content-Disposition: attachment; filename=\"document.pdf\""); header("Cache-Control: no-cache"); header("Expires: 0"); |
このコード例では、PDFファイルのダウンロードを促し、かつキャッシュを無効にする動作を実現できます。
注意しなければならないのが同じ種類のヘッダーを複数回送信する場合です。上書きされるかどうかに注意してください。headerには第2引数としてreplaceを設定できます。デフォルト値はtrueです。
2つのSet-Cookieを送信するコード例
header("Set-Cookie: token=abc123", false); header("Set-Cookie: theme=dark", false); |
このコード例のようにreplaceをfalseに設定すれば、同名ヘッダーを複数回送信できます。
関連記事
6.PHPでheaderの内容を取得する方法とは?
HTTPヘッダーは、Webアプリケーションの挙動を左右する重要な情報です。リダイレクトやContent-Typeの設定が正しく行われているか、意図したステータスコードが返っているかなど、開発者はレスポンスヘッダーを検証する必要があります。
ここでは、ブラウザやPHPを使ってHTTPレスポンスヘッダーを確認・取得する方法と、実際のデバッグに役立つテクニックを紹介します。
ブラウザでレスポンスヘッダーを確認する
もっとも手軽な方法は、ブラウザの開発者ツールを使ってレスポンスヘッダーを確認する方法です。ここでは、Google Chromeを例に手順を紹介します。
レスポンスヘッダーの確認手順(Chrome)
表示中のページで右クリック →「検証」を選択(またはF12キー)
上部タブから「Network(ネットワーク)」を選択
ページをリロード(Ctrl + R もしくはF5)
一覧から対象のリクエストをクリック
右側の「Headers」タブを開く
「Response Headers」欄を確認する。
FirefoxやEdgeなど他のブラウザでも同様の機能が用意されています。
PHPでheaderの内容を取得する(get_headers)
PHPにはレスポンスヘッダーを取得するためのget_headers関数があります。
コード例
$headers = get_headers("https://example.com/", 1); print_r($headers); |
このコード例では、指定したURLに対するHTTPレスポンスのヘッダー情報を連想配列として取得可能です。第2引数に1を指定すると、同名ヘッダーが複数存在する場合に配列として展開されます。
出力例
Array ( [Date] => Wed, 1 Jan 2025 10:00:00 GMT [Content-Type] => text/html; charset=UTF-8 [Server] => Apache [Location] => https://example.com/redirect ) |
なお、get_headersはサーバーへのHTTPリクエストを発行するため、対象のURLがダウンしているとエラーになることがあります。
PHPで送信前のheader内容を取得する(headers_list)
開発中のデバッグ作業などではheaders_list関数を使うと、headerで設定された内容を確認できます。出力前であればどのヘッダーが登録されているかを一覧で取得可能です。
コード例
header("Content-Type: application/json"); $headers = headers_list(); print_r($headers); |
外部サービスを活用する
Webベースのヘッダーチェッカーを使えば、レスポンス内容をブラウザ上で確認できます。外部からのアクセス視点で検証したい場合に便利です。
7.PHPでheaderを使ったときのエラーと解決方法
header関数は非常に便利ですが、エラーも起こりやすいです。ここでは、PHPでheaderを使ったときによくあるエラーと、その原因・解決方法について解説します。
headers already sent by ~
PHPでheader関数を実行した際に、次のような警告が表示されることがあります。
Warning: Cannot modify header information - headers already sent by (output started at /path/to/file.php:10) |
「ヘッダー情報はすでに送信されています」という意味で、HTTPレスポンスの本文がすでに出力されていて、ヘッダーを送信できないというエラーです。
「headers already sent by ~」で考えられるよくある原因と対応方法
このエラー「headers already sent by ~」が発生する場合、よくある原因があります。対応方法とともに紹介しましょう。
ファイルの冒頭に「改行」「空白」がある
PHPで書いたコードの冒頭に意図しない改行や空白が含まれていると、その時点でレスポンスの本文が送信されてしまいます。ファイルの冒頭に余計な空白や改行がないか確認するようにしてください。
特にUTF-8で保存する際は、BOM(Byte Order Mark)なしで保存しましょう。VSCodeなど多くのエディタではBOM無しでの保存が可能です。
BOMは文字コードの先頭に付加される特殊な目印を意味していて、コーディングしたファイルなどがどの文字エンコーディングされているのかを識別するために使われます。
PHPのコードをBOM付きのUTF-8で保存すると、ファイルの先頭に見えない3バイトのデータが出力されます。この3バイトが本文の出力とみなされてしまい、header関数でヘッダーを送信しようとしたときに「headers already sent by ~」のエラーを引き起こしますので注意してください。
echoやprintによる出力が先にある
headerより先に、echoやprintの処理があるとエラーになります。PHPでechoやprintの出力を行う前に、headerを書くようにしてください。
HTMLテンプレートとの組み合わせによる先出し
テンプレートエンジンや、header.phpなどの共通ファイルを読み込んだ時点で、HTMLの<doctype>や<html>タグが出力されていることがあります。この場合もヘッダーは送信できません。
ログインチェックや認証によるリダイレクトを行う場合は、HTML出力前の冒頭で条件分岐を実施することで回避可能です。
コード例
<?php session_start(); if (!isset($_SESSION['user_id'])) { header("Location: /login.php"); exit; } // ここからHTMLテンプレートを読み込む include 'header.php'; |
8.PHPのheader関数とWordPressのheader.phpとの違い
PHPを使っていると、PHPのheader関数とWordPressテーマ内のheader.phpを混同する人がいるようです。名前が似ているため混同されることがありますが、まったく異なる役割を持っています。ここでは、PHPのheader関数とWordPressのheader.phpとの違いについて解説します。
header関数はPHPの組み込み関数であり、Location, Content-TypeなどHTTPレスポンスヘッダーを出力するために使う関数です。それに対して、WordPressのheader.phpは、WordPressのテーマ内でロゴ、メニューなどWebページの上部「ヘッダー」部分を定義するテンプレートファイルです。
たとえばPHPで次のようなコードを見かけることがあります。
header("Location: /login.php"); |
これはページ遷移のためのHTTPヘッダーを送信している処理であり、WordPressのテンプレートとは関係ありません。
WordPressでは次のコード例のようにテンプレートファイルを読み込む関数が使われます。
<?php get_header(); ?> |
このコードは、テーマフォルダ内にあるheader.phpファイルの内容を読み込むための命令で、PHPのheader関数とは関係ありません。WordPressを使ったサイト作成時には、ビジュアルと構造に関わるheader.phpと、通信制御を担うPHPのheader関数を混同しないように注意してください。
9.PHPでheaderを安全に使うためのセキュリティ対策
header関数は便利ですが、使い方を誤るとセキュリティ上のリスクを招くおそれがあります。とくにリダイレクトやレスポンスヘッダーの設定は、悪意あるユーザーに狙われやすいため注意してください。ここでは、代表的な脅威とその対策を解説します。
オープンリダイレクトのリスクとその防止策
オープンリダイレクトとは、外部から指定された任意のURLへリダイレクトしてしまう脆弱性です。ログイン後の遷移やフォーム送信後の画面切り替えに$_GETの値を使っている場合に注意してください。
危険なコード例
$url = $_GET['redirect']; header("Location: {$url}"); exit; |
このようなコードでは攻撃者が任意のURLを指定して、ユーザーを偽サイトに誘導する危険がありますので、遷移先を固定するか、またはホワイトリスト管理してください。
$allowed = [ 'dashboard' => '/dashboard.php', 'home' => '/index.php' ];
$location = $allowed[$key] ?? '/index.php';
exit; |
このコード例のように事前に許可された遷移先だけを選択肢として用意し、それ以外は受け付けない構成にすることで、不正リダイレクトを防止できます。
また任意のURLを受け入れなければならない場合には、正規表現やparse_url関数を使ってドメインを検証し、信頼できるURLかどうかを判定する方法も有効です。
不正リクエスト対策に活かすレスポンスヘッダーの設定
レスポンスヘッダーは表示や通信の制御だけでなく、クライアント側の挙動を制限するセキュリティ対策としても機能します。クロスサイトリクエストフォージェリ(CSRF)やクロスサイトスクリプティング(XSS)への対策として、HTTPヘッダーが活用可能です。主な対策用ヘッダーは下表の通りです。
ヘッダー名 | 内容 |
---|---|
X-Content-Type-Options: nosniff | コンテンツのMIMEタイプを厳密に解釈させる |
X-XSS-Protection: 1; mode=block | XSS検知時に自動ブロック(モダンブラウザでは非推奨) |
Strict-Transport-Security | HTTPS通信を強制する(HSTS) |
Referrer-Policy | リファラの送信範囲を制御 |
セキュリティに関わるヘッダー設定
高いセキュリティレベルが求められる環境では、ヘッダーでの制御が欠かせません。クリックジャッキングやリファラ漏洩防止に関わる設定を検討をしてみましょう。
X-Frame-Options
他サイトによる<iframe>埋め込みを禁止するには、次のように設定します。
header("X-Frame-Options: SAMEORIGIN"); |
このヘッダーを付けると、同一オリジン以外からのフレーム表示が拒否され、クリックジャッキング攻撃を防止可能です。
Referrer-Policy
リファラは前のページのURLを次のページに伝える仕組みです。これが意図せず外部に漏れると、個人情報や遷移先のパラメータが知られてしまう恐れ性があります。
header("Referrer-Policy: no-referrer-when-downgrade"); |
この設定では、HTTPSからHTTPへの移動時にリファラを送信しません。用途に応じて、strict-originやsame-originを選ぶとよいでしょう。
関連記事
CakePHPとは?Webアプリ開発に必要な知識をわかりやすく解説します!
10.まとめ
本記事ではPHPのheader()関数の基本構文から、リダイレクト処理・Content-Typeの設定・エラー対応・セキュリティ対策まで幅広く解説しました。HTTPレスポンスヘッダーの正しい理解と活用は、Web開発の品質と安全性を高める上で欠かせません。初学者の方も、実務に活かしたいエンジニアの方も、ぜひ実際にコードを書きながら理解を深めてみてください。
本記事が皆様にとって少しでもお役に立てますと幸いです。
「フリーランスボード」は、数多くのフリーランスエージェントが掲載するITフリーランスエンジニア・ITフリーランス向けの案件・求人を一括検索できるサイトです。
開発環境、職種、単価、稼働形態、稼働日数など様々な条件から、あなたに最適なフリーランス案件・求人を簡単に見つけることができます。
単価アップを目指す方や、自分の得意なスキルを活かせる案件に参画したい方は、ぜひ「フリーランスボード」をご利用ください。
自身に最適なフリーランスエージェントを探したい方はこちらよりご確認いただけます。