もくじ


お問合せフォームを作りながらPHPを学ぶ

じつは、最初にPHPを学ぶのに使ったのはこの本。

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版) (DESIGNMAP BOOKS) Kindle版

その後に「誰もが~」をやって、今このお問い合わせの2周めをやっています。

誰もが~のときにメモらなかったことを主に書いていきます。

※自分用のノートなので、書籍を見ながら読む前提です(コードを追加する位置などここには詳細に書いていません)。可能であれば書籍とともにこのページをご利用ください。2023.9.11現在Unlimitedでも読める本です。

連想配列

連想配列のデータはキーと値でワンセット。複数のデータを格納できる。データは、ふつうの変数みたいにキーひとつに値ひとつでもいいし、配列みたいにキーひとつに値が複数でもいい。

$form = array();
$form['subject'] = "お仕事に関するお問い合わせ";

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

と書くと、連想配列$formsubjectキーにお仕事に関するお問い合わせという値が格納される。このセットはいくつでも入れられる。

変数と配列と連想配列の関係


ふつうの変数は値がひとつ、配列は値が複数、連想配列はキーと値のセットが複数でそれが普通の変数でも配列でもよい、という理解であっていますか?

ChatGPT

はい、あなたの理解は正しいです。

  • 通常の変数: 一つの値を持ちます。例: $variable = "value";
  • 配列: 複数の値を持ちます。インデックスが自動的に0から始まります。例: $array = array("value1", "value2", "value3");
  • 連想配列: キーと値のペアが複数あります。キーは任意の文字列や数値が使えます。値は普通の変数でも配列でもよいです。例: $associativeArray = array("key1" => "value1", "key2" => "value2");

PHPの配列は、実際には順序付きマップです。つまり、連想配列も配列の一種で、整数インデックスの配列と文字列キーの連想配列の両方を含めることができます。

例:
$mixedArray = array(
    "key1" => "value1",
    2 => "value2",
    "key3" => array("subvalue1", "subvalue2")
);

// 出力
echo $mixedArray["key1"]; // value1
echo $mixedArray[2]; // value2
echo $mixedArray["key3"][0]; // subvalue1

HTMLフォームから自動的につくられる連想配列$_POST

HTMLのフォームの場合、name属性がキーになり、valueが値になって、$_POSTというPHPが自動生成する連想配列に格納される。

echo "<pre>";
var_dump($_POST);
echo "</pre>";

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

これ書くと、

array(0) {

}

こんなふうに表示されるんだけど。

$_POSTはPHPが自動生成する連想配列。HTMLで書いたフォームのデータを自動格納する。var_dump($_POST);はチェックに便利だわ。
もし値に何か入っていれば、

array(5) {
  ["name"]=>
  string(6) "ぽん"
  ["email"]=>
  string(0) ""
  ["subject"]=>
  string(30) "その他のお問い合わせ"
  ["body"]=>
  string(30) "お昼ごはん何にする?"
  ["submit"]=>
  string(15) "確認画面へ"
}

こんなふうに、データ型とともに内容が表示される。

issetで変数や連想配列の値を確認する

フォームに何も入力されていないときにエラーを出すコードを書いたとき。そのフォームページに初めてアクセスしたときにもエラーコードが出たら困るので、これを回避する。

フォームに入力したら送信ボタン submit を押しますが、このキーが入っていないとき = はじめてそのページにアクセスしたときなので、エラーを出してはいけない。

isset関数でこれをチェック。

if(isset($_POST['submit'])) {
  送信ボタンが押された後の処理
}

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

こう書くと、関数は$_POSTsubmitというキーが存在し、その値がNULL(からっぽ)でないかを確認、空っぽでないときはtrueを返す。

キーが存在して、中身があるとき。(空の文字列でも中身とされる)

はじめてページにアクセスしたときはsubmitキーが存在していないのでこの関数はfalseを返し、{ }内の処理は行われない。

具体的に{ }内には、フォーム(他のキー)に空欄があったときに「入力されていません」と表示する処理が書いてある。

入力して送信ボタンを押した場合はsubmitキーは存在する。で、他のキーの中身もいちいちチェックして空欄があればメッセージを表示する。だから他のキーの中身が全部入っているときも、{ }内の処理は行われない。

NULLと、空の文字列


値が null であることと、空の文字列とは、別のことなのですね。

ChatGPT
はい、正確には異なります。PHPにおけるnullと空の文字列は異なるものとして扱われます。それぞれの特性について簡単に説明します。

  1. null:

    • 何も値を持たない変数。
    • 明示的に変数にnullを代入することで使用する。
    • isset関数は、変数がnullである場合falseを返す。
  2. 空の文字列 (""):

    • 文字としてのデータ型を持つが、中身は何もない。
    • 例: $var = "";
    • isset関数は、変数が空の文字列である場合trueを返す。

これを確認する簡単な例を見てみましょう。

$var1 = null;
$var2 = "";

// 以下の出力は false となる。
echo isset($var1) ? 'true' : 'false';

// 以下の出力は true となる。
echo isset($var2) ? 'true' : 'false';

したがって、nullと空の文字列は異なるものとして扱われ、特にisset関数を使用する際に注意が必要です。

関数は自動販売機のイメージ

書籍ではこんなふうに説明されていました。(文章そのままでなく、まとめています)

自動販売機の仕組みがわからなくても、使うことができる。
関数も仕組みが分からなくても使うことができる。

自動販売機はお金を入れる。
関数も呼び出すときにデータを渡す場合がある。

自動販売機では飲み物が出てくる。
関数もデータ(戻り値)が戻ってくる。(戻り値がない関数もある)

関数を呼び出しているコードは戻ってきた値に置き換わる。
お金は、飲み物に置き換わる!

これすごくわかりやすい例えでした。

未入力がないかチェックする

フォームに未入力があったときにメッセージを出す。「送信ボタンが押された後の処理」の一部分。


$errors = array();

$name = $_POST['name'];
~

if($name === "") {
  $errors['name'] = "お名前が入力されていません。";
}

echo "<pre>";
var_dump($errors);
echo "</pre>";

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より
  • $errors変数を作って、空の配列を入れてる。
  • $name変数を作って、そこに、HTMLフォームのデータが自動格納されている$_POSTの中のnameキーに対応する値を入れてる。
  • もし、$nameの値が""(空の文字列)だったら、$errorsのnameキーに"お名前が入力されていません。"という値を入れる。
  • $errorsの中身を表示する。

という感じ。

foreachで自動ループ処理

配列の中身を順番にひとつづつ取り出して、中身がなくなったら処理を終える。という便利な制御構造。
制御構造とは、プログラムの流れを制御するための構文(条件や繰り返しなど)。

echo "<ul>";
foreach($errors as $value) {
  echo "<li>";
  echo $value;
  echo "</li>";
}
echo "</ul>";

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

foreach($errors as $value) で、$errorsのキーと値を先頭から順に取り出して、値のみを$valueという変数に入れてる。そして{ }内の処理($valueの中身をliに出力)をする。

そしてまたforeach($errors as $value) に戻って、$errorsの中身がなくなるまで繰り返す。

キーと値の両方を処理したい場合は次のように書く。

foreach($errors as $key => $value) {
    // $key にはキーが、$value にはその値が代入される
}

※ChatGPTより

入力データを保持する

未入力があると再度入力してもらうために同じページが表示されるとき、入力してもらったデータをフォームに残したい。そんなとき。まず、

$name = htmlspecialchars($name, ENT_QUOTES);

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

フォームに入力された$nameの文字を処理して、再び$nameに代入する。

この、変数名が同じなのが初心者にはじつにややこしくて困るのよね。

ChatGPT

具体的には、$name 変数の中の特定の文字(<, >, &, ", ' など)がHTMLエンティティに変換され、その変換後の文字列が同じ $name 変数に上書きされる形となります。

このような自己代入は、PHPをはじめとする多くのプログラミング言語でよく見られる手法です。変数の内容を何らかの関数で加工・変換した後、同じ変数名でその結果を保存することが目的となります。

自己代入というのだそうです。

で、htmlspecialcharsとENT_QUOTESが何をしているかというと、

  • &&amp;
  • <&lt;
  • >&gt;
  • "&quot;(ENT_NOQUOTES フラグを指定しない場合)
  • '&apos; または &#039;(ENT_QUOTES フラグを指定した場合)

このように変換して、HTMLコードが入力されていても無効化している。

そして、$nameをフォームの中に出力すれば、入力してもらった値がそのままフォームに再表示される。

<input type="text" name="name" value="<?php if(isset($name)){ echo $name;} ?>"

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

セレクトボックスの値の保持

<select name="subject">
<option value="お仕事に関するお問い合わせ" <?php if(isset($subject) && $subject === "お仕事に関するお問い合わせ") {echo "selected";} ?>>お仕事に関するお問い合わせ</option>
<option value="その他のお問い合わせ" <?php if(isset($subject) && $subject === "その他のお問い合わせ"){echo "selected";} ?>>その他のお問い合わせ</option>
</select>

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

&&は、左辺と右辺がどちらもtrueのときのみ、trueを返す。

最初のoptionの場合、if(isset($subject)で、$subjectの値がNULL以外(空っぽでない)ときにtrueを返す。そして、$subject === "お仕事に関するお問い合わせ"で、その値が"お仕事に関するお問い合わせ"のときにtrueを返す。両方trueなので、&&はtrueを返す。

trueを返されたら、文字列"selected"を出力する。セレクトボックスはselectedで初期状態の選択項目を指定することができる。

セッション

<?php
session_start();

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

session_start()これ何?

ChatGPT

session_start() は、PHPでセッションを開始するための関数です。セッションとは、一定の時間内でのユーザーの操作を連続的に追跡するための仕組みです。具体的には、ユーザーがウェブサイトを訪問し始めてから離れるまでの間、ユーザー特有の情報(例:ログイン状態、カートの中身、設定値など)を保持するために使用されます。

中略

この情報は、ユーザーがウェブサイト内で移動する際に持ち越され、ログイン状態やユーザー名などの情報を参照することができます。

セッションを使用する際は、セッションを開始する前に session_start() を呼び出すことが重要です。また、セキュリティ上の理由から、セッションデータの扱いには注意が必要です。

まずこれを書く必要があるんですね。

で次。

if(count($errors) === 0) {
  $_SESSION['name'] = $name;
  $_SESSION['email'] = $email;
  $_SESSION['subject'] = $subject;
  $_SESSION['body'] = $body;

  header('Location: http://localhost/xxx/form2.php');
  exit();
}

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より
  • count($errors)は、$errorsのキーの数を数えて整数を返す。count関数。0、つまり未入力がなければ{ }内を実行。
  • $_SESSIONは、はPHPが自動生成する、セッション変数を格納するための連想配列。サーバー側で一次保存される。フォームに入力されたデータを格納している。
  • header('Location: sample/form2.php');でform2.phpに移動する。
  • exit();で処理を中断。

exit();について少し詳しく。

ChatGPT

正確には、このコードは次のような動作を行っています。

  1. header('Location: http://localhost/xxx/form2.php');
    • HTTPヘッダーを使用して、ブラウザに対して http://localhost/xxx/form2.php にリダイレクトするよう指示を送信します。この結果、ブラウザは指定されたURLに移動します。
  2. exit();
    • このスクリプトの実行を中断します。これにより、リダイレクト指示の後にスクリプトに記述されている追加のコード(もしあれば)が実行されることを防ぎます。

通常、header('Location: ...'); でのリダイレクト後に exit(); を使用するのは、リダイレクトが正確に実行されるようにするためのベストプラクティスとされています。リダイレクトヘッダーを送信した後にスクリプトが継続して実行されることを防ぐためです。

確認画面を作る

form2.phpにこのようにコードを書くと、フォームへの入力内容が別のページで表示される。(form1.phpにフォームがあり、未入力がなければform2.phpに移動)

<?php

session_start();

if(isset($_SESSION['name'])) {
  echo "<pre>";
  var_dump($_SESSION);
  echo "</pre>";
}
?>

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

とりあえず確認できるので、次はこれらをテーブルなどで整えて表示する。

その際、$_SESSIONから各値を取り出さなければならないので、
$name = $_SESSION['name'];みたいに書いていく。

※この書籍では、<!DOCTYPE html>より前にPHPコードを書いてる。

それから、

<form action="form3.php" method="post">
    <table><tr><th>お名前</th><td><?php echo $name; ?></td></tr>
      <tr><th>メールアドレス</th><td><?php echo $email; ?></td></tr>
      <tr><th>お問い合わせの種類</th><td><?php echo $subject; ?></td></tr>
      <tr><th>お問い合わせ内容</th><td><?php echo nl2br($body); ?></td></tr>
      <tr><td colspan="2"><input type="submit" name="submit" value="送信する"></td>
    </table>
  </form>
  <p><a href="form1.php?action=edit">入力画面へ戻る</a></p>

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

みたいな感じで書いていく。
お問い合わせの文章だけ、echo nl2br($body);と、nl2br関数が入ってる。
変なプログラムへの対策だとすれば、名前とメルアドにも入れてもよさそうだけど。

で、<a href="form1.php?action=edit">入力画面へ戻る</a>で入力画面に戻る。
?action=editこれをURLの後ろにくっつけて、GETメソッドでデータを送る。

action=editはたんに変数名=値です。任意でオケ。

そして、入力画面であるform1.phpのphpコードの最後にコードを追加して、GETメソッドで受け取ったデータを変数に入れ直す。

if(isset($_GET['action']) && $_GET['action'] === 'edit'){
  $name = $_SESSION['name'];
  $email = $_SESSION['email'];
  $subject = $_SESSION['subject'];
  $body = $_SESSION['body'];
}

PHP入門 確認画面付きのお問い合わせフォームをつくりながらPHPを学ぶ(第2版)より

もし$_GETにaction変数が存在してその中身があり、その中身がeditであれば、{ }内の処理をする。各変数の出力コードはフォームにすでに書いてある。