質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.11%

$_COOKIE に直接値を代入した場合 PHP7 での正しい動作とは?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,397

score 11

私が使用しているブログは php で構築されているのですが、 cookie を使って設定を保存する処理をしているところで、

  $_COOKIE[FOO]='';
  if($_POST['set_cookie']) {
    $_COOKIE[FOO].='value';
  }
  if($_COOKIE[FOO]){
    hoge;
  }

というコードが書かれています。

このコードの意図がよく分からないのですが、コード通りに解釈すると、

1)フォームの「設定保存」ボタンが押されると、 set_cookie が post される。
2)set_cookie が post されてきたら、$_COOKIE に保存されている cookie 名 FOO に値 'value' を追加する。
3)その上で、もし cookie 名 FOO に何らかの値がセットされていたら、 hoge を実行する。

という流れになっています。

疑問なのは、 $_COOKIE は cookie に設定された値を取り出すことのできるスーパーグローバル変数ですが、 cookie に値をセットするために上のように代入してよいのか?ということです。

私の予想では、代入しても $_COOKIE に値はセットされず、 cookie に値はセットされず、 setcookie() を使う必要があると思うのですが、実際に試したところ、値自体はこのスーパーグローバル変数にセットできるようです。でも、そうしたところで、 cookie を更新してくれるようには思えませんし、勝手に代入して値を変更してよいものかどうか疑問です。

ネットで php のリファレンスサイトなどを検索してみましたが、 $_COOKIE に値を代入する例や、代入した場合結果どのようなことが起こるかを説明したサイトが皆無でしたので、質問させてください。

current latest version である PHP7 での言語仕様として、上記操作を行った時の「正しい動作」は、どうなるのだと定義されているのでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m6u

    2019/08/14 17:58

    そういうコードの、参考にした情報(webページならurl、書籍なら書籍名とページ数)も示してほしいです。

    キャンセル

  • y.minori

    2019/08/14 18:03

    20年近く前のブログなので、もう当時のリファレンスの url が存在しないのです。

    キャンセル

回答 2

checkベストアンサー

+3

$_COOKIE の内容は PHP が呼び出されたとき(Web ブラウザから)、設定されるものであるため、あとから $_COOKIE の内容を変更したとしても、呼び出し元の情報には影響を与えません。
つまり単に代入しただけでは、 cookie は作られません。

$_COOKIE はスーパーグローバル変数ではありますが、書き込み不可ではありませんから、値を変更したとしてもそれが不正な動作というわけではないはずです。

多分ですが、hoge の中で $_COOKIE[FOO] を参照しているので、
少なくとも hoge に入る前にそこには設定だけはしておく必要がある、ということではないでしょうか。
※setcookie()を呼び出しても、反映されるのはその次のアクセスからであるため、hoge の中で見るには間に合わない

ただそうすると、先頭の

$_COOKIE[FOO] = '';


があるのはおかしい(常に実際の cookie の内容を無視することになる)ような気はします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/14 18:19

    ご説明ありがとうございました。

    >つまり単に代入しただけでは、 cookie は作られません。
    了解です。代入しただけでは cookie には反映されないので正解なのですね。すっきりしました。

    >※setcookie()を呼び出しても、反映されるのはその次のアクセスからであるため、hoge の中で見るには間に合わない

    なるほど、理解しました。確かにページがリロードされるまで setcookie() で変更した値は $g_COOKIE には反映されないので、即時反映しておくために敢えて書き込んでいるということなのですね。

    コード上、 set_cookie は値をセットする(フラグをONにする)場合に post されてくるので、
    $g_COOKIE[FOO] = ''; で、一旦 $g_COOKIE を空にしておいて、値をセットする場合には $g_COOKIE[FOO]に値を入れて、 hoge を実行するかどうかの if 文に利用して、その後、 $g_COOKIE にセットした値を使ってこのコードのうしろでフォームを表示させているのだと思います。

    キャンセル

+2

current latest version である PHP7 での言語仕様として、上記操作を行った時の「正しい動作」は、どうなるのだと定義されているのでしょうか。

スーパーグローバル変数はスコープの広い変数なので、他の変数と同じ挙動をする。
というのが定義で、$_COOKIEに関してだけ(他のスーパーグローバル変数もですが)代入時の挙動を定義したドキュメントというのは存在しないと思います。

このコードの意図がよく分からないのですが、コード通りに解釈すると、

set_cookie()してもそのリクエスト中には$_COOKIEの値は変更されないので、
$_COOKIEを$_SESSIONと同じ様に扱いたい時や一時変数を使いたくない時にこういう書き方をすることがあります。

多分、処理hogeの最後で$_COOKIEの内容を全部set_cookieしてるんじゃないかなと想像します。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/14 18:29

    >スーパーグローバル変数はスコープの広い変数なので、他の変数と同じ挙動をする。
    >というのが定義で、$_COOKIEに関してだけ(他のスーパーグローバル変数もですが)代入時の挙動を定義したドキュメントというのは存在しないと思います。
    なるほど。 $_COOKIE の役割が cookie の内容を参照すること( read )であることを考えると、 write できることは変な気がしますが、スーパーグローバル変数全て1つの扱いに統一されていて、用途的に分けてこの変数は read only 、というような個別の設定はないということですね。

    >set_cookie()してもそのリクエスト中には$_COOKIEの値は変更されないので、
    tacsheaven さんのご回答にも同様の示唆があり、おかげさまで理解しました。ご推察通り hoge の部分で setcookie() していて、その後ろで、 cookie の現在の状態を参照してフォームを表示していますので、リロードがかかる前なので $_COOKIE に値を代入してセットしておいた、ということなのですね。

    ご説明のおかげでクリアになりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る