フォームに名前を入力しました。
山田太郎
PHPでもちゃんと受け取れています。
ところが次のページへ移動すると――
さっきの名前がない。
「あれ?」
PHPで変数に入れたはずなのに。
$name = '山田太郎';
どうして次のページでは使えないのでしょう?
そしてAIに相談すると、こんなコードが返ってきました。
session_start();
さらに、
$_SESSION['name'] = $name;
今度は$_SESSIONです。
何やら難しそうですが、仕組みから考えればそれほど怖くありません。
今回は、
ページをまたいで情報を持っておくための「セッション」
について見ていきましょう。
事件発生:さっき入力した名前はどこへ行った?
まず、こんなPHPがあったとします。
input.phpからフォームを送信して、
<?php
$name = $_POST['name'];
echo $name;
ちゃんと、
山田太郎
と表示されました。
では、次のcomplete.phpでも、
<?php
echo $name;
と書けば表示されるでしょうか?
残念ながら、基本的にはそうなりません。
input.phpで作った、
$name
という変数が、そのまま自動的にcomplete.phpへ引き継がれるわけではないからです。
PHPの変数はずっと残っているわけではない
ここで大事なのが、
PHPの処理はリクエストごとに実行される
という考え方です。
たとえば、
input.phpへアクセス
↓
PHPが動く
↓
$nameを作る
↓
HTMLを返す
↓
処理終了
そして次に、
complete.phpへアクセス
↓
新しくPHPが動く
となります。
つまり、
別のPHPを開いたら、前のPHPで作った普通の変数が勝手についてくるわけではありません。
ここを知らないと、
さっき
$nameに入れたじゃん!
となります。
でもPHPからすると、
「それは前の処理の話です」
なのです。
でもWebサイトでは情報を引き継ぎたい
困りました。
Webサイトでは、ページをまたいで情報を使いたい場面がたくさんあります。
たとえば、
ログイン状態。
一度ログインしたのに、ページを移動するたびに、
メールアドレス:
パスワード:
を入力し直すサイトだったら大変です。
ほかにも、
お問い合わせフォームで、
入力
↓
確認
↓
完了
とページを移動するとき。
ショッピングサイトで、
商品をカートへ入れる
↓
別の商品を見る
↓
カートを見る
とするとき。
こうした場面では、
「この利用者は、さっき何をしていた?」
という情報をある程度引き継ぐ必要があります。
そこで使われる仕組みのひとつが、
セッション(session)
です。
セッションって何?
ものすごく簡単に言えば、
同じ利用者の一連のアクセスを関連づけて、一時的に情報を保持する仕組み
です。
たとえば、
$_SESSION['name'] = '山田太郎';
としておけば、適切にセッションを開始した別のPHPでも、
echo $_SESSION['name'];
のように情報を利用できます。
イメージとしては、
普通の変数
input.php
$name = '山田太郎';
↓ ページ移動
complete.php
$name は自動では引き継がれない
これに対して、
セッション
input.php
$_SESSION['name'] = '山田太郎';
↓ ページ移動
complete.php
$_SESSION['name'] を利用できる
という感じです。
session_start()って何?
セッションを使ったPHPを見ると、かなりの確率で登場するのが、
session_start();
です。
名前の通り、
セッションを開始・再開するための処理
です。
たとえば、
<?php
session_start();
$_SESSION['name'] = '山田太郎';
とします。
次のページでも、
<?php
session_start();
echo $_SESSION['name'];
とすれば、同じセッションの情報を利用できます。
初心者のうちは、
$_SESSIONを使うページでは、まずsession_start()が必要
と覚えておけば十分です。
$_SESSIONも「スーパーグローバル変数」
以前、
$_GET
と、
$_POST
が登場しました。
今回の、
$_SESSION
も似た形をしていますね。
これらはPHPで、
スーパーグローバル変数
と呼ばれる特別な変数です。
今の段階で名前まで暗記する必要はありません。
大切なのは、
$_GET
URLなどから受け取った値。
$_POST
POSTで送られてきた値。
$_SESSION
セッションに保存されている値。
くらいに役割を区別できることです。
$_SESSIONの中には複数の情報を入れられる
セッションには名前だけでなく、
$_SESSION['name'] = '山田太郎';
$_SESSION['email'] = 'example@example.com';
のように複数の情報を入れられます。
そして、
echo $_SESSION['name'];
なら名前。
echo $_SESSION['email'];
ならメールアドレス。
というように取り出せます。
形を見ると、
以前扱った配列と似ています。
$_SESSION['name']
の、
name
が「どの情報?」を表す目印になっています。
事件発生:Undefined array key “name”
ここで、過去の記事のエラーが帰ってきます。
こんなコードを書きました。
<?php
session_start();
echo $_SESSION['name'];
すると、
Undefined array key "name"
が出ました。
見覚えがありますね。
PHP学科第2回で扱ったエラーです。
これは、
$_SESSIONの中にnameというキーがない
可能性を考えられます。
たとえば、その前に、
$_SESSION['name'] = '山田太郎';
が実行されていなかった。
あるいはセッションが想定どおり引き継がれていない。
つまり今回も、
エラー文が何を言っているのか読めれば、調査する方向が見えてきます。
isset()で確認する
存在するか分からない値をいきなり、
echo $_SESSION['name'];
と使うのではなく、
if (isset($_SESSION['name'])) {
echo $_SESSION['name'];
}
のように確認する方法があります。
isset()は簡単に言えば、
「その値はセットされていますか?」
を確認するものです。
これもPHPでは非常によく見かけます。
AIが、
if (isset($_SESSION['user_id'])) {
のようなコードを書いてきたら、
「user_idというセッション情報があるか確認しているんだな」
くらいに読めればOKです。
ログイン機能でSESSIONをよく見る理由
ログイン処理では、
$_SESSION['user_id'] = 123;
のようなコードを見ることがあります。
これは、
「この利用者は誰なのか」を後のページでも判断するため
に使われる例です。
たとえば、
ログインページ
↓
ID・パスワードを確認
↓
ログイン成功
↓
セッションに利用者を識別する情報を保存
↓
マイページ
↓
セッションを確認
という流れです。
だから既存のPHPサイトを修正していると、
session_start();
や、
$_SESSION
によく遭遇します。
セッションはブラウザの中に全部保存されているの?
ここは少しだけ踏み込みます。
初心者だと、
$_SESSION['name']の中身が、そのままブラウザに保存されているの?
と思うかもしれません。
一般的なPHPセッションでは、サーバー側にセッションデータを保持し、ブラウザ側にはそのセッションを識別するためのIDをCookieなどで持たせます。
ざっくり、
ブラウザ
「私はこのセッションです」
↓
セッションID
↓
サーバー
「このIDなら、このセッション情報だな」
という関係です。
細かい仕組みを今すぐ覚える必要はありません。
ただ、
セッション=ブラウザへ全部の情報をそのまま保存すること
ではない、という点だけ覚えておきましょう。
Cookieとは違うの?
ここで、
Cookie(クッキー)
という言葉を知っている人もいるでしょう。
セッションとCookieは関係がありますが、同じものではありません。
今回は、
セッション情報を識別するためにCookieが利用されることがある
くらいで十分です。
Cookieそのものについては、別の記事で扱ったほうが分かりやすいでしょう。
セッションは永遠には残らない
$_SESSIONへ入れたら、
永久保存!
というわけでもありません。
セッションには有効期間や破棄の仕組みがあります。
ブラウザやサーバー側の設定、プログラムの処理などによって終了します。
つまり、
$_SESSION
はデータベースのような、
長期間保存するための仕組みとは別物
です。
基本的には、
一連のWeb操作の中で一時的に状態を持たせる
ための仕組みだと考えると分かりやすいでしょう。
ログアウトではセッションを消す
ログインがセッションを使っているなら、
ログアウトするときには、そのログイン状態を終わらせる必要があります。
たとえば、
session_start();
session_destroy();
のようなコードを見ることがあります。
destroyは、
破棄する
という意味です。
ただし実際のログアウト処理では、セッション変数のクリアやCookieへの対応なども含め、設計に応じた適切な処理が必要です。
初心者の段階では、
session_start()
セッションを開始・再開。
session_destroy()
セッションを破棄する処理。
という役割が読めれば十分です。
「session_start()したのに動かない!」
セッションを使っていると、こんなエラーに遭遇することがあります。
headers already sent
そして、
session_start()
という文字も出ている。
「セッションが壊れた?」
と思うかもしれません。
実はsession_start()では、Cookieなどに関係するHTTPヘッダーを扱う場合があります。
そのため、
HTMLなどを出力したあとにsession_start()を実行すると問題になることがあります。
たとえば、
<h1>マイページ</h1>
<?php
session_start();
?>
よりも、
<?php
session_start();
?>
<h1>マイページ</h1>
のように、基本的には出力より前でセッションを開始する形をよく見かけます。
見えない空白が原因になることも
さらに厄介なのが、
PHPの前に意図しない空白や出力があるケースです。
←ここに何か出力がある
<?php
session_start();
見た目では気づきにくい場合もあります。
もし、
Cannot modify header information
headers already sent
などが出たら、
session_start()より前に何か出力していないか?
という調査方向を持てます。
全部を自力で直せなくても、
何を疑えばいいか分かる。
オコジョキャンパスでは、まずそこを目指します。
AIに相談するときは「ページの流れ」も伝える
セッションの問題をAIに相談するとき、
$_SESSIONが取れません。
だけでは情報が足りないことがあります。
たとえば、
input.php
↓ POST
confirm.php
↓
complete.php
というページ構成なら、それも伝えます。
さらに、
confirm.phpで$_SESSION['name'] = $_POST['name'];
としています。
complete.phpで$_SESSION['name']
が取得できません。両方のPHPで
session_start()しています。
と伝える。
するとAI側も、
どこで情報を保存し、どこで取り出そうとしているのか
を追いやすくなります。
第10回では、
ファイル構成をAIに伝える
ことが重要でした。
今回は、
ページ遷移も伝える
ことが重要です。
コードだけでなく「流れ」を見る
ここまで来るとPHPも少し変わってきました。
最初のころは、
echo
や、
$_POST
など、コード一つひとつを見ていました。
でも実際のWebサイトでは、
フォーム入力
↓
confirm.php
↓
セッションへ保存
↓
complete.php
↓
セッションから取得
のように、
複数ページの流れ
で処理が作られています。
だから不具合が起きたときも、
「この1行は正しい?」
だけでなく、
「どのページで値を作り、どこへ渡している?」
を見る必要があります。
これができるようになると、AIが作ったPHPもかなり読みやすくなってきます。
今日の合格ライン
今回覚えてほしいのは4つです。
1. 普通の変数は、別ページへ自動的に引き継がれるわけではない。
2. ページをまたいで一時的に情報を保持する仕組みのひとつがセッション。
3. PHPでは$_SESSIONを使ってセッション情報を扱える。
4. セッションを使うページではsession_start()が重要。
コードを全部暗記する必要はありません。
AIが、
session_start();
if (isset($_SESSION['user_id'])) {
と書いてきたときに、
「ああ、ログイン状態か何かをセッションで確認しているんだな」
と想像できれば、今日のところは合格です。
ワンポイント答え合わせ
login.phpで、
$name = '山田太郎';
としました。
そのあとmypage.phpへ移動して、
echo $name;
と書きました。
名前は自動的に引き継がれるでしょうか?
A:引き継がれる
B:普通の変数なので、自動的には引き継がれない
答えは、
Bです。
ページをまたいで状態を持たせたい場合は、目的に応じてセッションなどの仕組みを使います。
そして、
$_SESSION
を見つけたら、
「前後のページにも関係しているかもしれない」
と考えてみてください。
エラーが起きたPHPファイルだけを眺めるのではなく、
その前にどこから来た?
その次にどこへ行く?
まで見る。
Webプログラムを調査するうえで、とても大切な視点です。
