お世話になります。
PHPMyadminを使用しておりますが、
SQL文を実行しているところ、エラーが出てきてしまいます。
Macで、XAMPPを使用しております。これまでに設定ファイルなどは触っていませんのでデフォルト状態であります。
common_function.php
1function get_dbh() { 2 // データの設定 3 // XXX 実際は、configファイル等で外出しにする事が多い 4 $user = 'root'; 5 $pass = ''; 6 $dsn = 'mysql:dbname=test;host=localhost;charset=utf8mb4'; 7 // 接続オプションの設定 8 $opt = array ( 9 PDO::ATTR_EMULATE_PREPARES => false, 10 ); 11 // 「複文禁止」が可能なら付け足しておく 12 if (defined('PDO::MYSQL_ATTR_MULTI_STATEMENTS')) { 13 $opt[PDO::MYSQL_ATTR_MULTI_STATEMENTS] = false; 14 } 15 // 接続 16 try { 17 $dbh = new PDO($dsn, $user, $pass, $opt); 18 } catch (PDOException $e) { 19 // XXX 本当はもう少し丁寧なエラーページを出力する 20 echo 'システムでエラーが起きました'; 21 exit; 22 } 23 return $dbh; 24}
ob_start(); session_start(); require_once('common_function.php'); date_default_timezone_set('Asia/Tokyo'); $user_input_data = array(); // 「パラメタの一覧」を把握 $params = array('name', 'post', 'address', 'birthday_yy', 'birthday_mm', 'birthday_dd'); // データを取得する foreach($params as $p) { $user_input_data[$p] = (string)@$_POST[$p]; } $error_flg = false; $error_detail = array(); // エラー情報の詳細を入れるための配列を用意する // 必須チェックを実装 $validate_params = array('name', 'post', 'address', 'birthday_yy', 'birthday_mm', 'birthday_dd'); foreach($validate_params as $p) { // 空文字(未入力)なら if ('' === $user_input_data[$p]) { // 「必須情報の未入力エラー」であることを配列に格納しておく $error_detail["error_must_{$p}"] = true; // 例えば「名前が未入力」の場合は、key名は「error_must_name」となる // エラーフラグを立てる $error_flg = true; } } if (1 !== preg_match('/\A[0-9]{3}[- ]?[0-9]{4}\z/', $user_input_data['post'])) { // 「郵便番号のフォーマットエラー」であることを配列に格納しておく $error_detail["error_format_post"] = true; // エラーフラグを立てる $error_flg = true; } $int_params = array('birthday_yy', 'birthday_mm', 'birthday_dd'); foreach($int_params as $p) { $user_input_data[$p] = intval($user_input_data[$p]); } if (false === checkdate($user_input_data['birthday_mm'], $user_input_data['birthday_dd'], $user_input_data['birthday_yy'])) { $error_detail["error_format_birthday"] = true; // エラーフラグを立てる $error_flg = true; } // CSRFチェック if (false === is_csrf_token()) { $error_detail["error_csrf"] = true; $error_flg = true; } // エラーが出たら入力ページに遷移する if (true === $error_flg) { // エラー情報をセッションに入れて持ちまわる $_SESSION['output_buffer'] = $error_detail; // 入力値をセッションに入れて持ちまわる // XXX 「keyが重複しない」はずなので、加算演算子でOK $_SESSION['output_buffer'] += $user_input_data; // 入力ページに遷移する header('Location: ./form_insert.php'); exit; } // DBハンドルの取得 try{ $dbh = get_dbh(); $sql = 'INSERT INTO test_form(name, post, address, birthday, created, updated) VALUES (:name, :post, :address, :birthday, :created, :updated);'; $pre = $dbh->prepare($sql); // 値のバインド $pre->bindValue(':name', $user_input_data['name'], PDO::PARAM_STR); $pre->bindValue(':post', $user_input_data['post'], PDO::PARAM_STR); $pre->bindValue(':address', $user_input_data['address'], PDO::PARAM_STR); // $birthday = "{$user_input_data['birthday_yy']}-{$user_input_data['birthday_mm']}-{$user_input_data['birthday_dd']}"; $pre->bindValue(':birthday', $birthday, PDO::PARAM_STR); $pre->bindValue(':created', date(DATE_ATOM), PDO::PARAM_STR); $pre->bindValue(':updated', date(DATE_ATOM), PDO::PARAM_STR); // SQLの実行 $r = $pre->execute(); }catch(PDOException $e){ var_dump($e); if (false === $r) { echo 'システムでエラーが起きました'; exit; } } // ダミーのOK:後で削除する echo 'OK';
みなさま色々な指摘ありがとうございます。
form_insert.phpの中身を全文載せさせていただきました。
仮にtryの中でエラーが出てもcatchしちゃってエラーも表示させないんじゃ何が原因かも分からない
まずはtry-catchの構文を取り除いてエラー内容を確認したら?try-catch入れるのは基本動作が問題無く動くようになった時点で入れたら良いよ
どんなINSERT文が出来上がっているのか確認して、phpMyAdminに直接投げ込んでみるとわかりますよ。
tryで接続部分を書いていたところを
if文で
if($dbh = new PDO($dsn, $user, $pass, $opt)){
print('接続できました');
}else{
print('接続に失敗しました');
}
としたところ、接続できましたの方が表示されたので接続はできていて、
INSERTの方が悪いとみていいのでしょうか?
insert実行までぜんぶtryに入れて拾得したExceptionをvar_dump($e);して確認してください。
「エラーが出た」と仰っていますが質問本文にはエラーが記載されていませんし。
mts10806さん
こういうことでしょうか?
もし下記のようであればOKと表示されているのですが、
データベースに何も変化が起こっていないので
間違えていますでしょうか?
try{
$dbh = get_dbh();
// INSERT文の作成と発行
// ------------------------------
// 準備された文(プリペアドステートメント)の用意
$sql = 'INSERT INTO test_form(name, post, address, birthday, created, updated)
VALUES (:name, :post, :address, :birthday, :created, :updated);';
$pre = $dbh->prepare($sql);
// 値のバインド
$pre->bindValue(':name', $user_input_data['name'], PDO::PARAM_STR);
$pre->bindValue(':post', $user_input_data['post'], PDO::PARAM_STR);
$pre->bindValue(':address', $user_input_data['address'], PDO::PARAM_STR);
//
$birthday = "{$user_input_data['birthday_yy']}-{$user_input_data['birthday_mm']}-{$user_input_data['birthday_dd']}";
$pre->bindValue(':birthday', $birthday, PDO::PARAM_STR);
$pre->bindValue(':created', date(DATE_ATOM), PDO::PARAM_STR);
$pre->bindValue(':updated', date(DATE_ATOM), PDO::PARAM_STR);
// SQLの実行
$r = $pre->execute();
}catch(PDOException $e){
var_dump($e);
/*
if (false === $r) {
// XXX 本当はもう少し丁寧なエラーページを出力する
echo 'システムでエラーが起きました';
exit;
}
*/
}
// ダミーのOK:後で削除する
echo 'OK';
ちなみに SELECT は動くんですか? if (defined('PDO::MYSQL_ATTR_MULTI_STATEMENTS')) { はなんでシングルクオーテーションで囲ってるんですか? $user_input_data は初期化してないようですが問題ないんですか?
form_insert.phpの全文を載せさせていただきました。
SELECTはまだ中身が何もないので実行していません。
一応、言っておきますと、catchで $rは拾えません。スコープが違います。
また、いずれにしてもExceptionの時点でエラーなので、たいていのケースでresultは入りません。
※try内で異常(エラー)があればそこで処理中断して問答無用でcatchにいきます。
あと「データベースに何も変化が起こっていない」とはどのタイミングでどのように確認したのでしょうか。
CREATE TABLE test_form (
`test_form_id` bigint unsigned NOT NULL AUTO_INCREMENT
`name` varchar(128) NOT NULL
`post` varchar(8) NOT NULL
`address` varchar(256) NOT NULL
`birthday` date NOT NULL
`created` datetime NOT NULL
`updated` datetime NOT NULL COMMENT
PRIMARY KEY (`test_form_id`)
)CHARACTER SET 'utf8mb4', ENGINE=InnoDB;
これらがテーブル作成時の記述で
データベースの方で値を挿入し
SELECT文で取って表示することは可能でした。
require_once('common_function.php');
// DBハンドルの取得
$dbh = get_dbh();
// SELECT文の作成と発行
$sql = 'SELECT * FROM test_form;';
$pre = $dbh->prepare($sql);
// SQLの実行
$r = $pre->execute();
if (false === $r) {
echo 'システムでエラーが起きました';
exit;
}
$data = $pre->fetchAll(PDO::FETCH_ASSOC);
//var_dump($data);
?>
質問を編集して追記してください。
コメント欄はマークダウン使えませんしデフォルトでは非表示です。
それに何度かお願いしているように「エラーが出てきてしまいます。」のエラーが質問本文に追記されていませんので。
https://teratail.com/help/question-tips#questionTips3-4-2