[PHP] setcookie() は、あらゆる出力よりも前にコールしなければいけません

クッキーでデータを記録する

setcookie() の使い方がおかしい

復習がてら「10日でおぼえるPHP5入門教室 第2版」を読みながら、サンプルプログラムを動かしてたら、setcookie()の使い方がおかしいコードがあったのでメモ。

サンプルコードそのまんま書いても動かない系のやつ。

動かないサンプルプログラム

サンプルプログラムは、クッキー情報を活用しよう的なプログラムで、次のような仕様。

  1. 1回目のアクセスで、メールアドレスを入力して送信
  2. 送信時、クッキーに入力したメールアドレスを保存
  3. 2回目にアクセスした時に、メールアドレスが自動的に表示される

といったプログラム。

以下、2つのファイルを使う。

cookie.php
<html>
    <head>
        <title>クッキーでデータを記録する</title>
    </head>
    <body>
        <form method="POST" action="cookie_rec.php">
            メールアドレス:
            <input type="text" name="email" size="30" maxlenght="50"
             value="<?php print($_COOKIE['email']); ?>" />
            <input type="submit" value="送信" />
        </form>
    </body>
</html>
cookie_rec.php
<html>
    <head>
        <title>クッキーでデータを記録する</title>
    </head>
    <body>
        <?php setcookie('email', $_POST['email'],
          time() + (60 * 60 * 24 * 90)); ?>
            クッキーを保存しました。
    </body>
</html>

で、cookie.phpのURLにアクセスして、メールアドレスを送信すると以下のメッセージが表示され、クッキーへの保存ができない。

Warning: Cannot modify header information - headers already sent by (output started at /Applications/XAMPP/xamppfiles/htdocs/php10/day03/cookie_rec.php:6) in /Applications/XAMPP/xamppfiles/htdocs/php10/day03/cookie_rec.php on line 7

setcookie()の仕様

setcookie()の仕様を確認してみる。

setcookie() は、その他のヘッダ情報と共に 送信するクッキーを定義します。 ほかのヘッダ情報と同様に、 クッキーは、スクリプトによる他のあらゆる出力よりも前に 送信される必要があります(これはHTTPプロトコルの制約です)。 <html> や <head> タグはもちろん 空白も含め、あらゆる出力よりも前にこの関数をコールするようにしなければなりません。

PHP: setcookie - Manual

ですよねー/(^o^)\

setcookie() の呼び出しは先頭に

というわけで、setcookie()の呼び出しは、先頭に持ってくる必要があります。

cookie_rec.php
<?php setcookie('email', $_POST['email'],
    time() + (60 * 60 * 24 * 90)); ?>
<html>
    <head>
        <title>クッキーでデータを記録する</title>
    </head>
    <body>
       クッキーを保存しました。
    </body>
</html>

これで無事に動きました。

まぁ、この本自体も少し古いし、何とも言えないけど…(最新版では修正されてたりするのかな)関数の仕様はよく確認してから使いましょう、という話。

10日でおぼえるPHP入門教室 第4版
山田 祥寛
翔泳社
売り上げランキング: 19,141