PDOを利用した会員登録フォームのチェックボックスの渡し方について - PHPプロ!Q&A掲示板

4964

  • 0P

PDOを利用した会員登録フォームのチェックボックスの渡し方について

質問日時 / 2018年7月17日 14:53    回答数 / 3件

Questioner:  moomin0225  このエントリーをはてなブックマークに追加 

キーワード / PDO    フォーム    チェックボックス   

初めて投稿させていただきます。
PDOの正しい利用方法がどの記事を見てもピンとこず質問させていただきました。
以下コードですが、

<?php
require 'password.php';   // password_verfy()はphp 5.5.0以降の関数のため、バージョンが古くて使えない場合に使用
// セッション開始
session_start();

$db['host'] = "***.*.*.*";  // DBサーバのURL
$db['user'] = "********";  // ユーザー名
$db['pass'] = "********";  // ユーザー名のパスワード
$db['dbname'] = "*****_*****";  // データベース名

// エラーメッセージ、登録完了メッセージの初期化
$errorMessage = "";
$signUpMessage = "";

// ログインボタンが押された場合
if (isset($_POST["signUp"])) {
// 1. 電話番号の入力チェック
if (empty($_POST["tel"])) { // 値が空のとき
$errorMessage = '電話番号が未入力です。';
} else if (empty($_POST["password"])) {
$errorMessage = 'パスワードが未入力です。';
} else if (empty($_POST["password2"])) {
$errorMessage = 'パスワードが未入力です。';
}

if (!empty($_POST["tel"]) && !empty($_POST["password"]) && !empty($_POST["password2"]) && $_POST["password"] === $_POST["password2"]) {

// 変数宣言
$tel = $_POST["tel"];
$password = $_POST["password"];
$stationPost = $_POST["station"];
if (isset($_POST['station']) && is_array($_POST['station'])) {
$station = implode(", ", $_POST["station"]);
}

var_dump($station)."<br>";
echo count($stationPost)."<br>";

$stationCount = count($stationPost);
$stationRe = "";
for ($count = 0; $count < $stationCount; $count++){
// 実行する処理
$stationRe = $stationRe.", ?";
}



// SQL文作成
$sql = 'INSERT INTO userData ( tel, password, '.
$station.
' ) VALUES ( ?, ?'.$stationRe.' )';

var_dump($sql);

// 2. ユーザIDとパスワードが入力されていたら認証する
$dsn = sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4;port=3307;',$db['host'],$db['dbname']);

// 3. エラー処理
try {
$pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));

$pass = password_hash($password, PASSWORD_DEFAULT);

$stmt = $pdo->prepare($sql);
$stmt->bindParam(':tel', $tel, PDO::PARAM_STR);
$stmt->bindParam(':password', $pass, PDO::PARAM_STR);
foreach ($stationPost as $row) {
$i = 1;
foreach ($row as $data) {
$stmt->bindParam($i++, $data, PDO::PARAMA_STR);
}
$stmt->execute();
}
$userid = $pdo->lastinsertid();  // 登録した(DB側でauto_incrementした)IDを$useridに入れる

$signUpMessage = '登録が完了しました。あなたの登録IDは '. $userid. ' です。パスワードは '. $password. ' です。';  // ログイン時に使用するIDとパスワード
} catch (PDOException $e) {
$errorMessage = 'データベースエラー';
// $e->getMessage() でエラー内容を参照可能(デバッグ時のみ表示)
echo $e->getMessage();
}
} else if($_POST["password"] != $_POST["password2"]) {
$errorMessage = 'パスワードに誤りがあります。';
}
}
?>

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>新規登録</title>
</head>
<body>
<h1>新規登録画面</h1>
<form id="loginForm" name="loginForm" action="" method="POST">
<fieldset>

<legend>新規登録フォーム</legend>
<div><font color="#ff0000"><?php echo htmlspecialchars($errorMessage, ENT_QUOTES); ?></font></div>
<div><font color="#0000ff"><?php echo htmlspecialchars($signUpMessage, ENT_QUOTES); ?></font></div>

<label for="tel">電話番号(ハイフン不要)</label>
<input type="text" id="tel" name="tel" placeholder="電話番号を入力" value="<?php if (!empty($_POST["tel"])) {echo htmlspecialchars($_POST["tel"], ENT_QUOTES);} ?>">
<br>

<label for="password">パスワード</label>
<input type="password" id="password" name="password" value="" placeholder="パスワードを入力">
<br>

<label for="password2">パスワード(確認用)</label>
<input type="password" id="password2" name="password2" value="" placeholder="再度パスワードを入力">
<br>

<!-- 最寄駅 -->
<label for="abeno">
<input type="checkbox" id="abeno" name="station[]" value="abeno">
阿倍野駅</label>

<label for="abiko">
<input type="checkbox" id="abiko" name="station[]" value="abiko">
あびこ駅</label>

<br>

<!-- フォーム送信ボタン -->
<input type="submit" id="signUp" name="signUp" value="新規登録">

</fieldset>
</form>
<br>
<form action="Login.php">
<input type="submit" value="戻る">
</form>
</body>
</html>


以上のような書き方など色々試してチェックボックスのチェック状態でSQL文はうまく可変するようにできましたのですが、
foreachの部分あたりの記述が間違っておりnumberやらトークンのエラーが出ます。
なんとかチェックボックスの状態(複数選択可)を会員情報としてテーブルに保存したいというのが目的ですので、是非お力添えいただけませんでしょうか。
何卒宜しくお願いいたします。

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┗A01shimix>>CODE foreach ($stationPost as $row) { $i = 1;
 ┗A01-1moomin0225返答ありがとうございます。 元のフォームとしては
  ┗A01-1-1shimixご提示いただいたformから推測するに、テーブル側にab

回答一覧

並び替え:

A01
answerershimix [7月17日 16:08]

  1. foreach ($stationPost as $row) {
  2. $i = 1;
  3. foreach ($row as $data) {
$stationPost(=$_POST["station"])が配列なのはわかりますが、その各要素も配列なんでしょうか?(元の$_POSTから見ると3次元配列)。

∴ 元のformを提示してください。



(蛇足)
telとpasswordでbindParamで0と1を利用済みなのに、重複して 1 に割り当てているように思えます(++$i でなく、$i++ なので加算前の値が使われる)。

この意見に回答する

ツリーへ TOPへ

A01-1
replyermoomin0225 [7月17日 16:25]

返答ありがとうございます。

元のフォームとしては、

telやpasswordは配列ではありません。
stationのみが配列となります。

<label for="tel">電話番号(ハイフン不要)</label>
<input type="text" id="tel" name="tel" placeholder="電話番号を入力" value="<?php if (!empty($_POST["tel"])) {echo htmlspecialchars($_POST["tel"], ENT_QUOTES);} ?>">
<br>

<label for="password">パスワード</label>
<input type="password" id="password" name="password" value="" placeholder="パスワードを入力">
<br>

<label for="password2">パスワード(確認用)</label>
<input type="password" id="password2" name="password2" value="" placeholder="再度パスワードを入力">
<br>

<!-- 最寄駅 -->
<label for="abeno">
<input type="checkbox" id="abeno" name="station[]" value="abeno">
阿倍野駅</label>

<label for="abiko">
<input type="checkbox" id="abiko" name="station[]" value="abiko">
あびこ駅</label>


としております。
未熟なばかりにコピペ繋ぎでおかしな部分がある事は重々承知なのですが、
以上のフォームの場合の正しいPDOの記述方法を教えていただけますと非常に助かります。
どうかよろしくお願いいたします。

この意見に回答する

ツリーへ TOPへ

A01-1-1
replyershimix [7月17日 18:44]

ご提示いただいたformから推測するに、テーブル側にabenoとかabikoというカラムがあって、それに(チェックボックスがチェックされていたら)abenoとかabikoという文字列を格納するのですよね?

#テーブルの設計がどうなんだろうという気もしますが、
#それはひとまず置いといて(汗

$_POST['station']としてPOSTされるべき値をphp側でも保持すべきです。配列の要素として不適切な文字列のものをPOSTされる可能性がゼロではありません(元のformを信用せずにチェックするのがセキュリティ対策の基本です)。保持している配列に存在しない文字列がPOSTされたら、いずれにしてもテーブル側にカラムが存在しませんからね。

パスワード2の一致とかは省いて基本的な部分だけなら下記のように書けると思います。
  1. <?php
  2. $errmsg = array();
  3.  
  4. if ((isset($_POST['tel']))&&(is_string($_POST['tel']))) {
  5.   $tel = trim($_POST['tel']);
  6.   if ($tel === '') {
  7.     $errmsg[] = 'telが空白です';
  8.   }
  9. } else {
  10.   $errmsg[] = 'telがありません';
  11. }
  12.  
  13. if ((isset($_POST['password']))&&(is_string($_POST['password']))) {
  14.   $password = trim($_POST['password']);
  15.   if ($password === '') {
  16.     $errmsg[] = 'passwordが空白です';
  17.   }
  18. } else {
  19.   $errmsg[] = 'passwordがありません';
  20. }
  21.  
  22. // スクリプト側でstationの値を保持
  23. $arr = array('abeno''abiko');
  24.  
  25. $station = array();
  26. if ((isset($_POST['station']))&&(is_array($_POST['station']))) {
  27.   foreach ($_POST['station'] as $val) {
  28.     if ((is_string($val))&&(in_array($val$arr))) {
  29.       $station[] = $val;
  30.     } else {
  31.       // あとの処理で、$errmsg の有無でエラーにすること
  32.       $errmsg[] = '不正なstation:' . $val;
  33.     }
  34.   }
  35. } else {
  36.   $errmsg[] = 'stationがありません';
  37. }
  38.  
  39. // 入力エラーチェック
  40. if (count($errmsg) > 0) { die(implode('<br>'$errmsg));
  41.  
  42. // SQL文組み立て
  43. $sql = sprintf('INSERT INTO userData ( tel, password, %s) VALUES (%s)'implode(''$station)implode(''array_fill(0count($station)+2'?')));
  44.  
  45. // executeで引き渡すデータ
  46. $data = array_merge(array($telpassword_hash($passwordPASSWORD_DEFAULT))$station);
  47.  
  48. $stmt = $pdo->prepare($sql);
  49. $stmt->execute($data);

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
ログファイルの中の空のデータ行を削除したい
 このエントリーをはてなブックマークに追加 
A
ログのデータ個数(列数)が固定で、空のログが"<><><>"だと既知であれば if ($line === "<><><>") { continue; } で読み飛ばしてもいいのでは? ...

>>続きを読む

まずは配列や文字列の扱いから、じっくり勉強して行きましょう。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)