ラジオボタンには正しくラベルを設置しましょう
押しやすさのために
あとビジュアル的に切り離してやるのも大事
cssでpaddingをとってやるといい
input_t.phpを実際に動く形にする
まず受け取ります。
$_POST["t_name"];
→これがもし空っぽだとまずい
→isset(いずせっと)というのを使う
isset($_POST["t_name"]);//trueかfalseを返す
存在すると「ある」と返す
empty($_POST["t_name"]);
存在しないと「true」と返す
ところで実際「未入力」で送ると情報はどうなるのか?
print_rで確認してみよう
Array ( [t_name] => [grade] => 1 [trem] => 1 [type] => 1 )
キーネーム(t_name)が来ちゃってる。
テキストボックスは未入力でも空文字が返されてしまうので「あります」になってしまう。
よってissetで判定すると少々まずい
emptyだと存在していても値が空だと「empty」となる。
値じゃなく存在そのものがなくてもemptyとなる
こちらの方がこの判定にはよろしい
なおissetとemptyはお察しの通り、true/falseが反転して出力される。
if(empty($_POST["t_name"])
||empty($_POST["grade"])
||empty($_POST["trem"])
||empty($_POST["type"])){
}else{
}
checkedをいれてしまっていたので本来このif文の後半はとばせるはずだけど、
それだとさらに「確認画面」が入用になるので、何もつけないのがよろしい?らしい。
header("Location:tests_form.php");//リダイレクトする
exit();//リダイレクトとセットで記述
ロケーションの最初は大文字で記述。
ところでリダイレクトのurlをミススぺるとこうなります。
[#IMAGE|a0396706_09242619.png|202001/30/06/|mid|812|484#]
こういうのがでる。
SQL文を書くときは極力半角スペースを入れないほうがいい。
下手にスペースをあけるとマシンが誤解する可能性があるらしい
不用意にスペースを使わないほうがよろしい
(特に括弧の中でカンマ区切りとか)
ここまで
--->insert_t.php
<?php
//デバック用の関数
//var_dump($_POST);//受け取れているかのテスト
print_r($_POST);//どっちの記述でもよろしい
//isset($_POST["t_name"]);//trueかfalseを返す/今回はよろしくない
if(empty($_POST["t_name"])
||empty($_POST["grade"])
||empty($_POST["trem"])
||empty($_POST["type"])){//trueの時。すなわち入力不備あり
header("Location:tests_form.php");//リダイレクトする
exit();//リダイレクトとセットで記述
}else{
//PDOでデータベースへの登録
print_r("good");
//まず基本の4セット
$user="root";
$pass="";
$host="localhost";
$dbname="school";
//データソースネーム 書式は項目名=値セミコロン。変数の周りは中かっこで必ず囲う。3連発。
$dsn = "mysql:host={$host};dbname={$dbname};chaset=utf8";
//PDOを生成 パラメータは3つ必要
$pdo = new PDO($dsn,$user,$pass);//データベースに接続する
//実行するためのsql文を記述(testsテーブルに入れるのでそのテーブルを確認する)
//前半はカラム構成
//後半は「外から受け取ったものは直接入れてはいけない」という鉄則がある
//よってプレイスホルダー(名前付きのあなぽこ)をVALUESに設定する
//それらはコロン+名前で設定する。コロンを付ける→プレイスホルダーと見做される
$sql = "INSERT INTO tests(t_name,grade,term,type) VALUES (:t_name,:grade,:term,:type)";
//焼きあがった構文はprepareと呼ばれる。先にコンパイルしてしまえと。
//パン生地は戻り値で戻って来るらしいのでそれを変数で受け取る必要があるらしい
//おそらくそれが$stmtである
$stmt = $pdo->prepare($sql);//こんがり。
//こんがり焼けたもののなかにあなぽこが開いている状態
//バインドバリューというのを使う
//1:どこ(:t_name)に2:何($_POST["t_name"])を入れるか3:それは数字(PARAM_INT)か文字(PARAM_STR)か
//の3つの引数が要る
//もし仮に引っ張ってくるのが日付型ならPARAM_STRらしい
//もしブーリアン型なら1か0になりINTになるらしい
//第3パラメータはSTRかINTかしかない。
$stmt->bindValue(":t_name",$_POST["t_name"],PDO::PARAM_STR);
$stmt->bindValue(":t_grade",$_POST["t_grade"],PDO::PARAM_INT);
$stmt->bindValue(":t_term",$_POST["t_term"],PDO::PARAM_INT);
$stmt->bindValue(":t_type",$_POST["t_type"],PDO::PARAM_INT);
//トッピングが完了したらそのstmtをエグゼキュートする
$stmt->execute();
//データ処理が終わったらそのページにはとどまってはいけない鉄則により、
header("Location: tests_list.php");
exit();
}//else終わり
?>
サーバにデータが追加されないとき:
可能性1
SQL文がバグだ
可能性2
PHPがバグだ
→
このときはheaderをコメントアウトして画面に表示されるエラーを確認
エラーが出なければ可能性1
これはなんだ?
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in C:\xampp\htdocs\php\makino\school\insert_t.php on line 57
まずいくつもミスがあった
しかしエラーが出た行がここ
$stmt->execute();
この行自体にミスがないというのが役に立たない
↓
①まず変数とかの名前が間違っていた
正解:grade ミススペル:t_grade
②これが一番ハテナだが、このinsert_t.phpのミススペルじゃなくて「送り元の」「tests_form.php」の「term」が「trem」になっていた。これは本当に発見できなかった
1.executeできなかったのでエラーがでたが、
2.executeできないのはstmtの文章が違っているからで、ミススペルはその行じゃない
3.場合によってはそのファイルですらない
しかもそのエラーが再現できないのだ。
意味が分からない。
1学期<input type="radio" name="term" id="term1" value="1">
にスペルミスのtremがあったが、それならif文ではじかれてelseには来ないだろうと思う
ああ、if文も間違っていたからかー。
発見できないわけだ
1.送り元のphpにタイプミス
2.同じタイプミスを受け手のif文でもしたのでif文が通る
3.データベースのカラム名と合わないので、もっとも最後の部分でだけエラーがでた
こういう構造だ。
あともうひとつ気づいたことがある
termを全部tremとミススぺったことに半分の原因がある
つまり知らない単語を不用意に使うなということ
でも自分がDBも構築してればいいが、人様の仕事を引き継ぐとなると
どうしようもないだろうなあ。
--->tests_form.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>テスト登録</title>
<link rel="stylesheet" href="css/style.css">
<script src="../jquery-3.4.1.min.js"></script>
</head>
<body>
<div id="container">
<h1>新規テストの登録</h1>
<form action="insert_t.php" method="post">
<!--4行2列-->
<table>
<tr>
<th><label for="t_name">テスト名</label></th>
<td><input type="text" name="t_name" id="t_name"></td>
</tr>
<tr>
<th>学年</th>
<td>
<label>
1年<input type="radio" name="grade" id="grade1" value="1"><!-- checked="checked">-->
</label>
<label>
2年<input type="radio" name="grade" id="grade2" value="2">
</label>
<label>
3年<input type="radio" name="grade" id="grade3" value="3">
</label>
</td>
</tr>
<tr>
<th>学期</th>
<td>
<label>
1学期<input type="radio" name="term" id="term1" value="1"><!-- checked="checked">-->
</label>
<label>
2学期<input type="radio" name="term" id="term2" value="2">
</label>
<label>
3学期<input type="radio" name="term" id="term3" value="3">
</label>
</td>
</tr>
<tr>
<th>テストの種類</th>
<td>
<label>
中間<input type="radio" name="type" id="type1" value="1"><!-- checked="checked">-->
</label>
<label>
期末<input type="radio" name="type" id="type2" value="2">
</label>
<label>
その他<input type="radio" name="type" id="type3" value="3">
</label>
</td>
</tr>
</table>
<p><button type="submit">登録</button></p>
</form>
<p id="msg"></p>
</div>
<script src="js/form.js"></script>
</body>
</html>
--->tests.list.php
<?php
$user = "root";
$pass = "";
$host = "localhost";
$dbname="school";
$dsn = "mysql:host={$host};dbname={$dbname};charset=utf8";
$sql="SELECT * FROM tests";
$pdo = new PDO($dsn,$user,$pass);
$res=$pdo->query($sql);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
<link rel="stylesheet" href="css/style.css">
<script src="../jquery-3.4.1.min.js"></script>
</head>
<body>
<table class="hoge">
<tr>
<th>ID</th><th>テスト名</th><th>学年</th><th>学期</th><th>タイプ</th>
</tr>
<?php
while($row=$res->fetch(PDO::FETCH_ASSOC)){
echo("<tr>");
echo("<td>{$row["t_id"]}</td>");
echo("<td>{$row["t_name"]}</td>");
echo("<td>{$row["grade"]}</td>");
echo("<td>{$row["term"]}</td>");
echo("<td>{$row["type"]}</td>");
echo("</tr>\n");
}
?>
</table>
<script src="js/list.js"></script>
</body>
</html>
--->style/css
body{
background: #eff;
background-image: url("../img/fish_kue2.png");
}
#container{
width: 80%;
margin: auto;
}
table{
border: solid 1px #ccc;
border-collapse: collapse;/*隣接セルを重ねる*/
background: #fff;
}
td, th{
border: solid 1px #ccc;
padding: 0.2rem 0.5rem;
}
.hoge tr:last-child{
color:#f00;
}
label{
padding-right:2rem;
}