質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

6回答

8889閲覧

DB登録処理のページでFatal errorが出てしまいます...2

earnest_gay

総合スコア615

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/06/20 04:30

編集2016/06/20 06:05

DB登録処理のページでまたFatal error:が出てしまいます...

同じような質問が3回続いて申し訳ございません。
英語は本当にダメなので申し訳ないですが教えてください...

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens' in C:\xampp\htdocs\xxx\register_human_thanks.php:34 Stack trace: #0 C:\xampp\htdocs\xxx\register_human_thanks.php(34): PDOStatement->execute(Array) #1 {main} thrown in C:\xampp\htdocs\xxx\register_human_thanks.php on line 34

何が原因でどうすればよいでしょうか?

一応ソース載せておきます。

<?php session_start(); $dsn = 'mysql:dbname=test;host=localhost;charset=utf8'; $user = 'root'; $password = ''; $option = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); $pdo = new PDO($dsn, $user, $password, $option); $stmt = $pdo->prepare("INSERT INTO user_data() VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//基本項目22個 $stmt->execute([ $_SEESION['join1']['email'], password_hash($_SEESION['join1']['pw'],PASSWORD_DEFAULT), $_SEESION['join1']['name1'], $_SEESION['join1']['name2'], $_SEESION['join1']['name3'], $_SEESION['join1']['name4'], $_SEESION['join1']['name5'], $_SEESION['join1']['name6'], $_SEESION['join1']['name7'], $_SEESION['join1']['year'], $_SEESION['join1']['month'], $_SEESION['join1']['day'], $_SEESION['join1']['gender'], $_SEESION['join1']['first_post'], $_SEESION['join1']['last_post'], $_SEESION['join1']['pref'], $_SEESION['join1']['city'], $_SEESION['join1']['town'], $_SEESION['join1']['building'], $_SEESION['join1']['tel1'], $_SEESION['join1']['tel2'], $_SEESION['join1']['tel3'] ]); $stmt = $pdo->prepare("INSERT INTO user_skill() VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//スキル年数MAX10セット*2=20セット(40個) $stmt->execute([ $_SEESION['jion2']['programs1_1'], $_SEESION['jion2']['programs_year1_1'], $_SEESION['jion2']['programs1_2'], $_SEESION['jion2']['programs_year1_2'], $_SEESION['jion2']['programs1_3'], $_SEESION['jion2']['programs_year1_3'], $_SEESION['jion2']['programs1_4'], $_SEESION['jion2']['programs_year1_4'], $_SEESION['jion2']['programs1_5'], $_SEESION['jion2']['programs_year1_5'], $_SEESION['jion2']['programs1_6'], $_SEESION['jion2']['programs_year1_6'], $_SEESION['jion2']['programs1_7'], $_SEESION['jion2']['programs_year1_7'], $_SEESION['jion2']['programs1_8'], $_SEESION['jion2']['programs_year1_8'], $_SEESION['jion2']['programs1_9'], $_SEESION['jion2']['programs_year1_9'], $_SEESION['jion2']['programs1_10'], $_SEESION['jion2']['programs_year1_10'], $_SEESION['jion2']['programs2_1'], $_SEESION['jion2']['programs_year2_1'], $_SEESION['jion2']['programs2_2'], $_SEESION['jion2']['programs_year2_2'], $_SEESION['jion2']['programs2_3'], $_SEESION['jion2']['programs_year2_3'], $_SEESION['jion2']['programs2_4'], $_SEESION['jion2']['programs_year2_4'], $_SEESION['jion2']['programs2_5'], $_SEESION['jion2']['programs_year2_5'], $_SEESION['jion2']['programs2_6'], $_SEESION['jion2']['programs_year2_6'], $_SEESION['jion2']['programs2_7'], $_SEESION['jion2']['programs_year2_7'], $_SEESION['jion2']['programs2_8'], $_SEESION['jion2']['programs_year2_8'], $_SEESION['jion2']['programs2_9'], $_SEESION['jion2']['programs_year2_9'], $_SEESION['jion2']['programs2_10'], $_SEESION['jion2']['programs_year2_10'] ]); $stmt = $pdo->prepare("INSERT INTO user_qualification() VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//資格年数MAX10セット(30個) $stmt->execute([ $_SEESION['jion2']['certificate1'], $_SEESION['jion2']['certificate_year1'], $_SEESION['jion2']['certificate_day1'], $_SEESION['jion2']['certificate2'], $_SEESION['jion2']['certificate_year2'], $_SEESION['jion2']['certificate_day2'], $_SEESION['jion2']['certificate3'], $_SEESION['jion2']['certificate_year3'], $_SEESION['jion2']['certificate_day3'], $_SEESION['jion2']['certificate4'], $_SEESION['jion2']['certificate_year4'], $_SEESION['jion2']['certificate_day4'], $_SEESION['jion2']['certificate5'], $_SEESION['jion2']['certificate_year5'], $_SEESION['jion2']['certificate_day5'], $_SEESION['jion2']['certificate6'], $_SEESION['jion2']['certificate_year6'], $_SEESION['jion2']['certificate_day6'], $_SEESION['jion2']['certificate7'], $_SEESION['jion2']['certificate_year7'], $_SEESION['jion2']['certificate_day7'], $_SEESION['jion2']['certificate8'], $_SEESION['jion2']['certificate_year8'], $_SEESION['jion2']['certificate_day8'], $_SEESION['jion2']['certificate9'], $_SEESION['jion2']['certificate_year9'], $_SEESION['jion2']['certificate_day9'], $_SEESION['jion2']['certificate10'], $_SEESION['jion2']['certificate_year10'], $_SEESION['jion2']['certificate_day10'] ]); $stmt = $pdo->prepare("INSERT INTO user_pr() VALUES (?, ?, ?, ?)");//その他自己PR $stmt->execute([ $_SEESION['join2']['major_cat'], $_SEESION['join2']['major_skill'], $_SEESION['join2']['agreement'], $_SEESION['join2']['pr'] ]); session_destroy(); ?>

6/20 14:11追記

プレースホルダーの数を修正し、user_data()の()を取り除いても一向にエラーが収まりません...

$stmt = $pdo->prepare("INSERT INTO user_data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//基本項目22個 $stmt->execute([ $_SEESION['join1']['email'], password_hash($_SEESION['join1']['pw'],PASSWORD_DEFAULT), $_SEESION['join1']['name1'], $_SEESION['join1']['name2'], $_SEESION['join1']['name3'], $_SEESION['join1']['name4'], $_SEESION['join1']['name5'], $_SEESION['join1']['name6'], $_SEESION['join1']['name7'], $_SEESION['join1']['year'], $_SEESION['join1']['month'], $_SEESION['join1']['day'], $_SEESION['join1']['gender'], $_SEESION['join1']['first_post'], $_SEESION['join1']['last_post'], $_SEESION['join1']['pref'], $_SEESION['join1']['city'], $_SEESION['join1']['town'], $_SEESION['join1']['building'], $_SEESION['join1']['tel1'], $_SEESION['join1']['tel2'], $_SEESION['join1']['tel3'] ]);

同じ34行目で
$_SEESION['join1']['tel3']
の部分です。

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1' in C:\xampp\htdocs\xxx\register_human_thanks.php:34 Stack trace: #0 C:\xampp\htdocs\IDH\register_human_thanks.php(34): PDOStatement->execute(Array) #1 {main} thrown in C:\xampp\htdocs\xxx\register_human_thanks.php on line 34


14:36 追記
カラム名を指定してみると、エラーの結果が若干変わりました。

$stmt = $pdo->prepare("INSERT INTO user_data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1' in C:\xampp\htdocs\xxx\register_human_thanks.php:34 Stack trace: #0 C:\xampp\htdocs\xxx\register_human_thanks.php(34): PDOStatement->execute(Array) #1 {main} thrown in C:\xampp\htdocs\xxx\register_human_thanks.php on line 34


$stmt = $pdo->prepare("INSERT INTO user_data(email, password, fname_kanji, lname_kanji, fname_kana, lname_kana, fname_roma, lname_roma, middle_name, birthday_year, birthday_month, birthday_day, gender, first_post, last_post, prefectures, city, town, building, tel1, tel2, tel3) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null' in C:\xampp\htdocs\xxx\register_human_thanks.php:34 Stack trace: #0 C:\xampp\htdocs\xxx\register_human_thanks.php(34): PDOStatement->execute(Array) #1 {main} thrown in C:\xampp\htdocs\xxx\register_human_thanks.php on line 34

テーブル構造です。
イメージ説明


15:02追記
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/20 04:31

英語がダメでも検索くらいはしたほうがいいと思います。 まるごとではなく共通っぽいメッセージ部分で検索すれば日本語の情報も沢山でてくるかと思いますので・・・
masaya_ohashi

2016/06/20 07:00

お小言ですが、直す度に次のエラー、直す度に次のエラーが出すぎです。 なぜここまでコードを組み上げてから初めて気付いたのか…少しずつコードを実装しながらその都度テストしていれば、問題が起きた時、問題のあるコードの箇所がかなり絞り込むことが出来たはずです。こまめな動作テストを心がけましょう。
guest

回答6

0

投稿2016/06/20 04:34

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

セッション用のグローバル変数間違ってませんか?

  • 誤:$_SEESION
  • 正:$_SESSION

投稿2016/06/20 06:21

編集2016/06/20 06:22
attakei

総合スコア2738

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/06/20 06:24

つい今気づきました(汗) お騒がせしました。 確認ページではecho h($_SESSION['join1']['email']使えているのに、 DBで登録するときにはなんでemailが空なんだと思っていたら Spellミスでした。 ありがとうございます。
guest

0

ベストアンサー

先程回答したものは先程のもので、ご質問時のエラーの解消になっていると思いますが、

$stmt = $pdo->prepare("INSERT INTO user_data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//基本項目22個

上記のように22パラメータに修正済みでさらにエラーがでているということであれば、別のエラーがでているとかはないですかね?

具体的にはuser_dataのテーブルはしっかり22カラムなのでしょうか?
id などauto_incrementになっているものや timestamp で設定されているようなものをuser_dataが別に持っているとすれば上記のクエリではINSERTできないかと思います。
全部のカラムを指定せずにINSERTする場合は対応するカラムの記述必須ですので、このあたりもう一度確認されてはいかがでしょう?

http://www.dbonline.jp/mysql/insert/index1.html

冒頭の通り、もし上記が原因であれば、最初にご質問されている時とは別のエラーがでているはずです。

追記

どちらにしてもカラム数多そうなので、

INSERT INTO user_data (カラム1, カラム2,,,,) VALUES ('カラム1', 'カラム2',,,,)

としっかりカラムを指定した上でINSERTする、下記のマニュアルのように名前付きのパラメータで指定する、
など作ろうとしているレコードと、実際のクエリやデータが本当に正しい形になっているかがわかりやすい書き方をしたほうが、後々のことを考えても良いかもしれないですね。

http://php.net/manual/ja/pdostatement.execute.php#refsect1-pdostatement.execute-examples

投稿2016/06/20 05:34

編集2016/06/20 05:39
obi_yuta

総合スコア121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masaya_ohashi

2016/06/20 05:40

他質問の内容ではuser_dataにはuser_idのカラムが先頭にあったはずです。INSERTでテーブルのカラム指定を省略したのであれば、VALUESのカラム数はテーブル全体のカラムの数と一致しなければなりません。
earnest_gay

2016/06/20 05:41 編集

回答ありがとうございます。 おっしゃられているとおり、しっかり22カラムではなくオートインクリメント付きのidカラムとtimestamp付きのcreatedカラムもあります。 テーブル構造を本質問に追記しました。
obi_yuta

2016/06/20 05:54 編集

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null' in C:\xampp\htdocs\xxx\register_human_thanks.php:34 Stack trace: #0 C:\xampp\htdocs\xxx\register_human_thanks.php(34): PDOStatement->execute(Array) #1 {main} thrown in C:\xampp\htdocs\xxx\register_human_thanks.php on line 34 ------- 追記でいただいている上記のエラーについては単に「emailが必須だけど空だよ」という内容なので、 $_SEESION['join1']['email']にしっかり値が入っているか確認されてはどうでしょう?(var_dumpとかechoとか) もしくは$_SEESION['join1']['email']の部分を適当な文字列にしたらどうですか?他のカラムも基本的にnot nullになっているようですので、一度すべて適当な値を指定してちゃんとレコードが作成されるか確認してみると原因の切り分けができてよいのではないでしょうか。(クエリがいけないのか、指定している値がいけないのか)
earnest_gay

2016/06/20 05:52

masaya_ohashiさん user_dataテーブルの先頭カラムは「id」ですよ。 「user_id」カラムが先頭にあるのはuser_data以外のテーブルの user_skill user_qualification user_pr の3テーブルです。 >>カラム指定を省略したのであれば、VALUESのカラム数はテーブル全体のカラムの数と一致しなければなりません。 これは知りませんでした。 貴重な情報ありがとうございます。
earnest_gay

2016/06/20 06:01

obi_yutaさん 回答ありがとうございます。 >>「emailが必須だけど空だよ」 んーおかしいです。 流れとして、 1.入力ページで入力する 2.確認画面で間違いがないか確認させる 3.問題なければthanksページに遷移してDBに登録する という流れなのですが、 「emailが空」なのであれば、確認画面で表示されないはずです。 でもちゃんと表示されています。 ↓一部抜粋 <td>E-mail (確認用)</td> <td><?php echo h($_SESSION['join1']['email_conf']); ?></td> これから本質問に画像を追記しますので見て頂けませんか?
earnest_gay

2016/06/20 06:20

ずらりと記述している $_SESSIONのつもりが $_SEESIONになってました。 これじゃ変数が未定義なのでemailに格納されていないわけです(汗) お騒がせしました。
obi_yuta

2016/06/20 06:23

$_SEESION -> $_SESSION で解決しましたか?
earnest_gay

2016/06/20 06:55

48行目からは脱出できましたが、別の行(79)で困り果ててます...
obi_yuta

2016/06/20 07:01

>> 別の行(79)で こちらは具体的にはどういったエラーですか? カラムを指定する、実際の値が入っているか確かめるなど、ここまでに解消したエラーへの対応をしても別のエラーが発生するということですかね?
earnest_gay

2016/06/20 07:30 編集

ありがとうございます。 未熟者にアドバイス頂ければと思います。 実は本質問は、全体の中の1部なので、 insertしているのはuser_dataテーブルだけではなく user_skill user_qualification user_pr もあるのです。 試しに user_skill user_qualification user_pr この3つのSQL文を削除し user_dataのSQL文だけで試したら、しっかりDBに登録されておりました。 user_prは4カラムしかないのでなんとか自分ひとりでも出来そうですが 課題はあと user_skill user_qualification の2つです。 まず、user_skillテーブルから解決していきたいと思います。 $stmt = $pdo->prepare("INSERT INTO user_skill VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//スキル年数MAX10セット*2=20セット(40個) $stmt->execute([ $_SEESION['jion2']['programs1_1'], $_SEESION['jion2']['programs_year1_1'], $_SEESION['jion2']['programs1_2'], $_SEESION['jion2']['programs_year1_2'], $_SEESION['jion2']['programs1_3'], $_SEESION['jion2']['programs_year1_3'], $_SEESION['jion2']['programs1_4'], $_SEESION['jion2']['programs_year1_4'], $_SEESION['jion2']['programs1_5'], $_SEESION['jion2']['programs_year1_5'], $_SEESION['jion2']['programs1_6'], $_SEESION['jion2']['programs_year1_6'], $_SEESION['jion2']['programs1_7'], $_SEESION['jion2']['programs_year1_7'], $_SEESION['jion2']['programs1_8'], $_SEESION['jion2']['programs_year1_8'], $_SEESION['jion2']['programs1_9'], $_SEESION['jion2']['programs_year1_9'], $_SEESION['jion2']['programs1_10'], $_SEESION['jion2']['programs_year1_10'], $_SEESION['jion2']['programs2_1'], $_SEESION['jion2']['programs_year2_1'], $_SEESION['jion2']['programs2_2'], $_SEESION['jion2']['programs_year2_2'], $_SEESION['jion2']['programs2_3'], $_SEESION['jion2']['programs_year2_3'], $_SEESION['jion2']['programs2_4'], $_SEESION['jion2']['programs_year2_4'], $_SEESION['jion2']['programs2_5'], $_SEESION['jion2']['programs_year2_5'], $_SEESION['jion2']['programs2_6'], $_SEESION['jion2']['programs_year2_6'], $_SEESION['jion2']['programs2_7'], $_SEESION['jion2']['programs_year2_7'], $_SEESION['jion2']['programs2_8'], $_SEESION['jion2']['programs_year2_8'], $_SEESION['jion2']['programs2_9'], $_SEESION['jion2']['programs_year2_9'], $_SEESION['jion2']['programs2_10'], $_SEESION['jion2']['programs_year2_10'] ]); です。 しかし、これは 1 PHP 2年 JAVA 2年 JavaScript 3年 ・・・・・・・ user_id skill1 year1 skill2 year2 skill3 year3 ・ ・ ・ ・ ・ の様に1:1のような構造になってるので 1 PHP 2年 1 JAVA 2年 1 JavaScript 3年 user_id skill year のような1:nの構造に変えたいのですが、 その前に知りたいことが2点あります。 まず分割してレコード挿入する場合の記述方法についてです。 $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ $_SEESION['join1']['user_id'],//←登録しようとしている人のID $_SEESION['jion2']['programs1_1'],//←PHPが入っている $_SEESION['jion2']['programs_year1_1'],//←1年が入ってる ]); $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ $_SEESION['join1']['user_id'],//←登録しようとしている人のID $_SEESION['jion2']['programs1_2'],//←JAVAが入ってる $_SEESION['jion2']['programs_year1_2'],//←2年が入ってる ]); このようにすれば分割して登録されるのでしょうか? 次に、「user_skillテーブルでのuser_id」は 「user_dataテーブルのid」と同値である必要があるのですが、 「user_dataテーブルのid」はオートインクリメントで自動的に数字が入ってくれます。 「user_skillテーブルでのuser_id」はどういう仕組みで「user_dataテーブルのid」と同値にさせることができるでしょうか? 例えば、 null PHP 2年 null JAVA 2年 null JavaScript 3年 このnullを毎回毎回、 このスキルは「user_dataテーブルのid」が58番の人のスキルだから、このカラムのnullは書き換えよう...と、管理者のような人が手動でやるのはなんかおかしいと思います。 登録するときに「user_skillテーブルでのuser_id」を「user_dataテーブルのid」と同値にするにはどうしたら良いかという質問です。 まずはこれが分からないと、テーブル構造変えられないので、先に進めないんです...] https://teratail.com/questions/38513
earnest_gay

2016/06/20 07:11

すいません。 先に返事してしまったので user_skill()など残ってます。 ちょっと試してから上記のエラー内容修正します!
obi_yuta

2016/06/20 07:20

そうですね。これまでご回答させていただいているものなど、一度ご確認ください。 これから、という話かもしれませんが、これだけのレコードを1処理でINSERTするのであれば(そうでなくてもですが)、しっかりとtry-catchなどの例外処理をする、トランザクション内で処理を行う、などしていったほうが良いかと思います。 もし想定になければすべて問題が解消したら調べてみていただけると良いかと思います。 http://php.net/manual/ja/pdo.begintransaction.php
earnest_gay

2016/06/20 07:57 編集

こういうことなのだと思いますがどうでしょうか? user_skillには(user_id,skill,year)の3つのカラムがある。 $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ $_SESSION['jion1']['user_id'], $_SESSION['jion2']['programs1_1'], $_SESSION['jion2']['programs_year1_1'], ]); $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ $_SESSION['jion1']['user_id'], $_SESSION['jion2']['programs1_2'], $_SESSION['jion2']['programs_year1_2'], ]); $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ $_SESSION['jion1']['user_id'], $_SESSION['jion2']['programs1_3'], $_SESSION['jion2']['programs_year1_3'], ]); レコード毎にスキルと年数は変動するが、 user_idは一意であるべきだから変わらず。 ここまではそれとなく分かるのですが、 $_SESSION['jion1']['user_id'], をどうやって取得するかです。 「user_dataテーブルのid」はオートンクリメント。 「user_skillテーブルでのuser_id」も「user_dataテーブルのid」と同じものにする必要がある。 だから $_SESSION['jion1']['user_id'], を 「user_dataテーブルのid」 に 紐づけるために $_SESSION['jion1']['user_id'], をどうやって取得するか? ここでかなり悩んでます。 出来るかどうかは分かりませんが、 思いつく方法としては下記が思いつきました。 $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ user_dataテーブルの一番新しい(番号が古い)id + 1, $_SESSION['jion2']['programs1_1'], $_SESSION['jion2']['programs_year1_1'], ]); $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ user_dataテーブルの一番新しい(番号が古い)id + 1, $_SESSION['jion2']['programs1_2'], $_SESSION['jion2']['programs_year1_2'], ]); $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ user_dataテーブルの一番新しい(番号が古い)id + 1, $_SESSION['jion2']['programs1_3'], $_SESSION['jion2']['programs_year1_3'], ]); これができれば常に 「user_skillテーブルでのuser_id」=「user_dataテーブルのid」 にできるのですが...
obi_yuta

2016/06/20 08:21

「user_dataテーブルの一番新しい(番号が古い)id+1」という方法だと、user_skillを作る前に別のuser_dataが作成されてしまったらすべてのデータがずれてしまいます。 PDOではlastInsertId()で最後に作成したレコードのidを取得することができます。 大まかな流れとしては、 ------- $stmt = $pdo->prepare("INSERT INTO user_data()..."); $stmt->execute(); $user_id = $pdo->lastInsertId(); // 作成されたレコードのidを取得 $stmt = $pdo->prepare("INSERT INTO user_skill...."); $stmt->execute([ $user_id, $_SESSION['jion2']['programs1_1'], $_SESSION['jion2']['programs_year1_1'], ]); .... // 同様に$user_idを使ってレコード作成 ------- といった感じです。詳しくは下記ご参照ください。 http://php.net/manual/ja/pdo.lastinsertid.php
obi_yuta

2016/06/20 09:52 編集

かなり省いていますが、トランザクションや例外処理も入れると下記のような感じになるかと思います。 -------------- <?php try { $dsn = 'mysql:dbname=test;host=localhost;charset=utf8'; $user = 'root'; $password = ''; $option = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); $pdo = new PDO($dsn, $user, $password, $option); try { $stmt = $pdo->prepare("INSERT INTO user_data..."); $pdo->beginTransaction(); $stmt->execute([,,,]); // user_data作成 $user_id = $pdo->lastInsertId(); // idを取得 $stmt = $pdo->prepare("INSERT INTO user_skill..."); $stmt->execute([ $user_id, // 取得したuser_data.idを指定 ,,, ]); $stmt = $pdo->prepare("INSERT INTO user_qualification..."); $stmt->execute([ $user_id, // 取得したuser_data.idを指定 ,,, ]); $stmt = $pdo->prepare("INSERT INTO user_pr..."); $stmt->execute([ $user_id, // 取得したuser_data.idを指定 ,,, ]); $pdo->commit(); // ここまでのレコードを実際に作成 } catch(PDOExecption $e) { $dbh->rollback(); // 例外が発生した場合ロールバックしてレコードを取消 // エラー表示など echo $e->getMessage(); } } catch( PDOExecption $e ) { // エラー表示など echo $e->getMessage(); } (コメントだと行頭のスペースが省かれてしまうんですね...)
earnest_gay

2016/06/20 08:54

こちらでも回答頂き少し理解できました。 https://teratail.com/questions/38575?whotofollow user_dataからINSERTしたレコードをユニークキーによるWHEREの絞り込みで取得する 処理されるタイミングを考えると、 WHEREの絞り込みでuser_dataのidを取得するできることに気づきました。 ページ単位で考えていたので気づかなかったです... $user_id = $pdo->lastInsertId(); これを「user_dataからINSERTしたレコードをユニークキーによるWHEREの絞り込みで取得する」に置き換えるとこうなりますでしょうか? $user_id = $pdo->query('SELECT id FROM user_data order by id desc');
earnest_gay

2016/06/20 08:56

トランザクションは聞いたことのない言葉で今少し調べていたのですが、ちょっとよくわからないです...
obi_yuta

2016/06/20 09:06

>> $user_id = $pdo->query('SELECT id FROM user_data order by id desc'); 上記のクエリだと、 1. user_dataを作成 2. user_skill を作成 もしこの1と2の間に別のuser_dataが作成されてしまったら、 user_idが狂ってしまいませんか? 普通にlastInsertIdで取得したidで良いと思いますよ。 $user_id = $pdo->lastInsertId(); >> トランザクション データ作成・更新処理の1まとまりと考えていただければ差し支え無いかと思います。 user関連データのすべての作成が成功したらすべてをDBに反映(commit)、ひとつでも失敗したらすべてを取消(rollback)、といった処理を行う上でのまとまりを指します。 beginTransaction()からcommit()もしくはrollback()までが1つのトランザクションです。 拝見する限り、個人情報を扱うようなプログラムを作ろうとされているようですので、この辺りの理解はしておかないと怖いことになるかと思います。。
earnest_gay

2016/06/20 09:33 編集

>>もしこの1と2の間に別のuser_dataが作成されてしまったら、 極論ですが、ミリ秒による時間差登録ということですよね? 1. user_dataを作成(ユーザーAによる登録) 2. user_dataを作成(ユーザーBによる登録) 3. user_skill を作成(ユーザーAによる登録) そうだった場合、lastInsertId();ではそれを防げるのでしょうか? トランザクションの解説ありがとうございます。 時間のある時に理解深めたいと思います
obi_yuta

2016/06/20 09:55

>> 極論ですが、ミリ秒による時間差登録 おっしゃるとおりです。 >> lastInsertId();ではそれを防げるのでしょうか? 防ぐことができます。 $pdo = new PDO($dsn, $user, $password, $option); // 略 $user_id = $pdo->lastInsertId(); の 「$pdo->lastInsertId()」となっているように、この接続に対して最後にinsertされてidだと思っていただければよいかと思います。同じように別のブラウザなどから実行された別の接続は接続で、その接続内で最後にinsertされた、といったように別の接続と競合することはありません。
earnest_gay

2016/06/20 10:00

user_skillは無事DB登録されていました。 DBの登録上エラーはありませんが、DBへ登録する際に値が入ってない状態で常にNULLが入るので問題があります。 全体を把握してもらいたいので少し長くなりますが... 一部ですがまず、入力ページで選択してもらいます。 ユーザーによってスキル数は変動しますのでjsで追加ボタンを実装してます。 記述はしてませんが、プレビューボタンを押すと当ページでのPOSTを全て$_SESSION['join2']に保存して、次ページへ遷移します。 <?php session_start(); if(!empty($_POST)){ $_SESSION['join2'] = $_POST; header('Location: register_human_preview.php'); } ?> <script type="text/javascript"> /*スキルエリアのセレクトボックスセットのクローン*/ function skill_selectAdd(){ var get = document.getElementById("skill_select"); var set = get.cloneNode(true); var target = document.getElementById("skill_selectAdd"); var btn_delete = document.getElementById("skill_select_btnDel"); set.id= "test" + target.children.length;//idの重複を防ぐため、連番をつけておく target.parentNode.insertBefore(set, target); btn_delete.disabled = false; } /*スキルエリアのセレクトボックスセットの削除*/ function skill_selectDel(){ var targets = document.getElementsByClassName("skill_select"); var btn_delete = document.getElementById("skill_select_btnDel"); if (targets.length === 2) { btn_delete.disabled = true; } targets[1].parentNode.removeChild(targets[targets.length - 1]);//最後の要素を削除 } </script> <tr id="skill_select" class="skill_select"> <td> <select name="programs1_[]"> <?php echo Programmerskill::getSkill(); ?> </select> </td> <td> <select name="programs_year1_[]"> <?php echo Skillyear::getYear(); ?> </select> </td> </tr> <tr id="skill_selectAdd"> <td colspan="2"> <input type="button" value="追加" onClick="skill_selectAdd()"> <input type="button" value="削除" onClick="skill_selectDel()" id="skill_select_btnDel" disabled="true"> </td> </tr> 次は、下記のようにして取り出して表示させています。(確認画面) <?php session_start(); ?> <tr> <td> <?php $arr = $_SESSION['join2']['programs1_']; for($i=0;$i < count($arr);$i++ ) { echo h($arr[$i]).'<br />'; } ?> </td> <td> <?php $arr = $_SESSION['join2']['programs_year1_']; for($i=0;$i < count($arr);$i++ ) { echo h($arr[$i]).'<br />'; } ?> </td> </tr> 最後に、ページ遷移してDB登録です。 <?php session_start(); ・ ・ ・ ・ ・ $user_id = $pdo->lastInsertId(); $stmt = $pdo->prepare("INSERT INTO user_skill(user_id,skill,year) VALUES (?, ?, ?)"); $stmt->execute([ $user_id, $_SESSION['jion2']['programs1_1'], $_SESSION['jion2']['programs_year1_1'], ]); ?> 確認画面ではそのまま配列として取り出してますが DB登録時にはINSERT毎に分けて取り出さないといけないので配列として取り出すことはできないと思うのですが、どうしたらよろしいでしょうか?
obi_yuta

2016/06/20 10:14

>> DBへ登録する際に値が入ってない状態で常にNULLが入るので問題 こちらは具体的にどういったカラムに対してnullが入ることが問題なのでしょうか? >> DB登録時にはINSERT毎に分けて取り出さないといけないので配列として取り出すことはできない こちらもちょっとどの部分かがわからないのでもう少し説明をしてもらえればです。
earnest_gay

2016/06/20 11:49 編集

この部分 $arr = $_SESSION['join2']['programs1_']; for($i=0;$i < count($arr);$i++ ) { echo h($arr[$i]).'<br />'; $arr = $_SESSION['join2']['programs_year1_']; for($i=0;$i < count($arr);$i++ ) { echo h($arr[$i]).'<br />'; と $stmt->execute([ $user_id, $_SESSION['jion2']['programs1_1'], $_SESSION['jion2']['programs_year1_1'], ]); だと思うのですが、 もともとのname属性は <select name="programs1_[]"> <?php echo Programmerskill::getSkill(); ?> </select> <select name="programs_year1_[]"> <?php echo Skillyear::getYear(); ?> </select> で、こうしてるのは動的に追加ボタンを実装している関係で https://teratail.com/questions/38124 を見て頂ければわかると思います。 >> DBへ登録する際に値が入ってない状態で常にNULLが入るので問題 $_SESSION['jion2']['programs1_1'], $_SESSION['jion2']['programs_year1_1'], ・ ・ ・ ・ ・ ・ これらは全部何も入ってないんですよ。 こうしちゃってるので... $arr = $_SESSION['join2']['programs1_']; >>どういったカラムに対してnullが入ることが問題なのでしょうか? 値がない場合はnullが入るようにしておかなかればエラーがでてしまうので nullが入ることが問題なのではなく、 値が入っていない(取り出せない)ことが問題なのです。
earnest_gay

2016/06/21 02:42

全てのSQL文でエラーがでず無事登録することができました。 昨日は長らくお付き合いいただきありがとうございました!
obi_yuta

2016/06/21 03:27

お返事しきれていない部分ありすいません。 無事解決できたとのことなによりです。
guest

0

エラー内容は大体こうです。
PHPの34行目にある不正なパラメータで、PDOの処理に例外が発生しました。変数の数とトークン(ここでは、SQLの中に記載してあるプリペアドステートメントの?のこと)が一致してないです。

最初のinsert処理の変数の数とトークンの数をもう一度見なおしてみては?

投稿2016/06/20 04:45

FKM

総合スコア3633

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/06/20 05:11

ありがとうございます。 全体を見直してみます。
guest

0

単純にprepareで設定しているパラメータの数とexecuteで指定しているパラメータの数が違っているからではないでしょうか。(22個とありますが、実際には24個あります…。)

$stmt = $pdo->prepare("INSERT INTO user_data() VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//基本項目22個

まるごとGoogleに翻訳させるでもいいですから、他の方もおっしゃっているようにもう少しエラーメッセージを読むことを試行されたほうがよいかもですね。

投稿2016/06/20 04:45

obi_yuta

総合スコア121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/06/20 05:10

ありがとうございます。 Google翻訳は使っているのですが、なかなか理解できないのです...
guest

0

最初のクエリしか確認してませんが。
$stmt = $pdo->prepare("INSERT INTO user_data() VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");//基本項目22個

?の数が24個あるのに対して、executeで指定しているのは22個。

あとエラーになっているかはわかりませんが、INSERT INTO user_data()のところ、テーブル名の後ろに()は不要かと。

投稿2016/06/20 04:44

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/06/20 05:09

ありがとうございます。 プレースホルダーの数を修正し、 user_data()の()を外してみましたが一向に直らないんです...
ttyp03

2016/06/20 05:41

14:36 追記 について エラーメッセージ見れば察しはつくと思いますが、emailがnullになってるからダメだよ的な感じじゃないですか?
ttyp03

2016/06/20 06:16

emailの情報が、$_SESSION['join1']['email_conf'] に入っているのであれば、これを使わないといけないのでは? $stmt->execute([ $_SEESION['join1']['email_conf'],
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問