質問するログイン新規登録

回答編集履歴

7

修正

2019/02/22 02:31

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -33,7 +33,7 @@
33
33
 
34
34
  これでvar_dump()の結果が
35
35
  `object(PDOStatement)#3 (1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" } `
36
- に返ってきていたら成功しています。
36
+ のように返ってきていたら成功しています。
37
37
  もし、`bool(false)` とだけ出ていたら失敗しています。
38
38
 
39
39
  ここで1点アドバイス。
@@ -64,7 +64,8 @@
64
64
 
65
65
  出ていないのでしたらようやく「キャスト(array)が邪魔」の対応ができます。
66
66
 
67
- 出ていない=queryはきちんと届けられていて成功している わけですがキャストをしてしまうことで無理やりコードを正常化してしまっていることになります。
67
+ 出ていない=queryはきちんと届けられていて成功している わけですが
68
+ キャストをしてしまうことで変数の型が変わります。
68
69
  foreachの前でこうしてみましょう。
69
70
  ```php
70
71
  var_dump((array)$stmt);
@@ -88,6 +89,13 @@
88
89
  - [初心者を戒めるPHP](https://qiita.com/tadsan/items/fb496e450fc27c8c4494)
89
90
  - [モダンPHPアンチパターン](https://qiita.com/tadsan/items/157969b338fd8b782b21)
90
91
 
92
+ foreach()には配列とオブジェクトのみ使えますが、
93
+ 何が入っているか確かめていない配列を(array)でキャストすることによって
94
+ 無理やりコードを正常化してしまっていることになります。
95
+ つまり、気づけたはずのエラーが気づけなくなるわけです。
96
+ これに限らずキャストが必要な場面はほとんどありません。
97
+ キャストするくらいなら変数が想定の情報を持ってきているかを確認した上で実行するように組んでください。
98
+
91
99
  # 2.配列の添え字で使うIDとidは別物。データベースの設定と合ってる? について
92
100
 
93
101
  これに加えてもう1つ確認すべき点があります。

6

修正

2019/02/22 02:31

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -32,7 +32,7 @@
32
32
  ※確認できたらいったん行頭に//をつけてコメントアウトしておくと良いです。
33
33
 
34
34
  これでvar_dump()の結果が
35
- `object(PDOStatement)#3 (1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }
35
+ `object(PDOStatement)#3 (1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" } `
36
36
  に返ってきていたら成功しています。
37
37
  もし、`bool(false)` とだけ出ていたら失敗しています。
38
38
 

5

修正

2019/02/22 01:14

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -23,7 +23,7 @@
23
23
  もちろん、デバッグのために$stmtが何をもっているか確認するのは必須です。
24
24
  ```php
25
25
  var_dump($stmt);
26
- if($stmt){
26
+ if(!$stmt){
27
27
  die('失敗');
28
28
  }
29
29
  //成功したときの処理

4

修正

2019/02/22 00:57

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -14,7 +14,7 @@
14
14
  try-catchを随所に書かれていますが、それは**プログラムが必ず成功するわけではないという前提**で書かれているもののはずです。
15
15
  で、あれば、そのqueryも**必ず成功するわけではないという前提**で対応しましょう。
16
16
  ```php
17
- if($stmt){
17
+ if(!$stmt){
18
18
  die('失敗');
19
19
  }
20
20
  //成功したときの処理

3

修正

2019/02/22 00:57

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -8,7 +8,7 @@
8
8
  0. キャスト(array)が邪魔
9
9
  0. 配列の添え字で使うIDとidは別物。データベースの設定と合ってる?
10
10
 
11
- # 1.について
11
+ # 1.キャスト(array)が邪魔について
12
12
  [PDO::query](http://php.net/manual/ja/pdo.query.php)の返却値は「PDOStatement オブジェクト」OR「false」です。
13
13
  つまり、返却値を確認してfalseでなければ、一応、queryは無事届けられたと思って良いです。
14
14
  try-catchを随所に書かれていますが、それは**プログラムが必ず成功するわけではないという前提**で書かれているもののはずです。
@@ -84,10 +84,12 @@
84
84
  echo $row['ID'];
85
85
  }
86
86
  ```
87
+ キャストを含めたコーディングで注意すべき点は下記のような記事が参考になります。
88
+ - [初心者を戒めるPHP](https://qiita.com/tadsan/items/fb496e450fc27c8c4494)
89
+ - [モダンPHPアンチパターン](https://qiita.com/tadsan/items/157969b338fd8b782b21)
87
90
 
91
+ # 2.配列の添え字で使うIDとidは別物。データベースの設定と合ってる? について
88
92
 
89
- 2.について
90
-
91
93
  これに加えてもう1つ確認すべき点があります。
92
94
  一応(array)キャストをすることで下記のような配列ができるのでforeachはできるはず。
93
95
  `array(1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }`

2

修正

2019/02/22 00:55

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -1,6 +1,127 @@
1
+ DBに接続する際には下記のような記事が参考になります。
2
+ - [PHPでデータベースに接続するときのまとめ](https://qiita.com/mpyw/items/b00b72c5c95aac573b71)
3
+
4
+ ですが、
5
+
1
6
  解決したいだけでしたら確認する点は二点です。
2
7
 
3
8
  0. キャスト(array)が邪魔
4
9
  0. 配列の添え字で使うIDとidは別物。データベースの設定と合ってる?
5
10
 
6
- **途中投稿してしまました。追記中です。少々お待ちください。**
11
+ # 1.につ
12
+ [PDO::query](http://php.net/manual/ja/pdo.query.php)の返却値は「PDOStatement オブジェクト」OR「false」です。
13
+ つまり、返却値を確認してfalseでなければ、一応、queryは無事届けられたと思って良いです。
14
+ try-catchを随所に書かれていますが、それは**プログラムが必ず成功するわけではないという前提**で書かれているもののはずです。
15
+ で、あれば、そのqueryも**必ず成功するわけではないという前提**で対応しましょう。
16
+ ```php
17
+ if($stmt){
18
+ die('失敗');
19
+ }
20
+ //成功したときの処理
21
+ ```
22
+
23
+ もちろん、デバッグのために$stmtが何をもっているか確認するのは必須です。
24
+ ```php
25
+ var_dump($stmt);
26
+ if($stmt){
27
+ die('失敗');
28
+ }
29
+ //成功したときの処理
30
+ ```
31
+
32
+ ※確認できたらいったん行頭に//をつけてコメントアウトしておくと良いです。
33
+
34
+ これでvar_dump()の結果が
35
+ `object(PDOStatement)#3 (1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }
36
+ に返ってきていたら成功しています。
37
+ もし、`bool(false)` とだけ出ていたら失敗しています。
38
+
39
+ ここで1点アドバイス。
40
+
41
+ 今のコーディング内容ではPDOExceptionをちゃんと拾うようにできていません。
42
+
43
+ `new PDO()`する際に幾つか引数をつけて実行していると思いますが
44
+ [PDO](http://php.net/manual/ja/pdo.construct.php)の引数、今のところは$dsn,$username,$passwordまでしか入れてませんよね?
45
+ その次の$optionに注目してください。
46
+ > ドライバ固有の接続オプションを指定するキー=> 値の配列。
47
+
48
+ ここで色々なOPTIONを指定することができますが、その中にATTR_ERRMODEというのがあります。([属性の説明](http://php.net/manual/ja/pdo.setattribute.php))
49
+ ここでPDO::ERRMODE_EXCEPTIONを指定することできちんとExceptionを拾うようになります。
50
+
51
+ 最初に提示したQiitaの参考記事では下記のように$optionsを指定していますね。
52
+ ```
53
+ [
54
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
55
+ PDO::ATTR_EMULATE_PREPARES => false,
56
+ ]
57
+ ```
58
+
59
+ 上記をPDO()接続時の引数に指定した上でもう一度実行してみてください。
60
+
61
+ そこで`エラーSQLSTATE[・・・・`のようなエラーメッセージが出てきたらその先のエラーコードとエラー理由を確認しましょう。
62
+ 参考:[エラーメッセージの読み方と対処, 検索や質問の原則](https://qiita.com/cannorin/items/eb062aae88bfe2ad6fe5)
63
+
64
+
65
+ 出ていないのでしたらようやく「キャスト(array)が邪魔」の対応ができます。
66
+
67
+ 出ていない=queryはきちんと届けられていて成功している わけですがキャストをしてしまうことで無理やりコードを正常化してしまっていることになります。
68
+ foreachの前でこうしてみましょう。
69
+ ```php
70
+ var_dump((array)$stmt);
71
+ ```
72
+
73
+ 結果は下記のようになっていませんか?
74
+ `array(1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }`
75
+
76
+ PDO::queryで折角取得できたPDOStatementがなくなってしまっています。
77
+ つまり、SELECT文の実行結果は「結果セット」つまり、データが入っているとイコールなので、そこがなくなってしまうと
78
+ 実行結果もなくなってしまうということになります。
79
+
80
+ 実行結果をそのまま素直にループさせれば良いです。
81
+ ```php
82
+ foreach ($stmt as $row) {
83
+ // 出力
84
+ echo $row['ID'];
85
+ }
86
+ ```
87
+
88
+
89
+ 2.について
90
+
91
+ これに加えてもう1つ確認すべき点があります。
92
+ 一応(array)キャストをすることで下記のような配列ができるのでforeachはできるはず。
93
+ `array(1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }`
94
+
95
+ コードでは`$row['ID']`を参照しようとしていますが、そのようなデータありません。
96
+ 連想配列そのまま回しているので$rowだけで`SELECT ID FROM TB_LIST`が取れるはず。
97
+ PHPにおいて、存在しないキーを参照しようとすると`Warning: Illegal string offset '指定名' `または`Notice: Undefined index`のようなエラーが出ます。
98
+ ※きちんとケースはありますが、どちらかが出てたら参照が間違っているという理解でいたらいいです
99
+
100
+ おそらく質問者さんの実行環境ではエラー表示が制御されているのではないでしょうか。
101
+
102
+ 学習段階、開発途中段階のコードでは何が起きるか分からないので、全てのレベルのエラー表示をするようにしておくことを強くすすめます。
103
+ - [エラー表示ON](https://qiita.com/shotets/items/3c95aef631b2c5eadae5)
104
+
105
+
106
+ 1.を全て対応した後でも想定通りの結果が出ない場合はここまでやってみてください。
107
+ 配列の添え字のキーを間違えていないか?大文字と小文字は別物です。
108
+
109
+ ```php
110
+ $hoge["a"] = "hello";
111
+ echo $hoge["d"]; // Notice: Undefined index: A
112
+ echo $hoge["A"]; // Notice: Undefined index: A
113
+ echo $hoge["a"]; // Hello
114
+
115
+ ```
116
+
117
+ ----
118
+
119
+ 以下、今後を見据えた場合の蛇足。
120
+
121
+ 0. データを出力するときは[HTMLエスケープ](http://php.net/manual/ja/function.htmlspecialchars.php)をしよう。
122
+ なぜそうすべきかというのは[XSS](https://gihyo.jp/dev/serial/01/javascript-security/0002)とかで調べると良いです。
123
+ 0. 今後、もしかしたら検索条件などを指定してデータを取得する機会があるかもしれませんが、そのときはSQLのエスケープは必ず行おう。PDO::queryよりも[PDO::prepareで「プリペアドステートメント」をセットしてからのbindValue](https://qiita.com/mpyw/items/b00b72c5c95aac573b71#pdoprepare--pdostatementbindvalue--pdostatementexecute-%E3%81%AE3%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%81%A7%E3%82%AF%E3%82%A8%E3%83%AA%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)がおすすめです。
124
+ なぜそうすべきかは[SQLインジェクション](https://academy.gmocloud.com/advance/20150608/700)とかで調べると良いです。
125
+
126
+
127
+ 以上。

1

途中投稿・・・

2019/02/22 00:52

投稿

m.ts10806
m.ts10806

スコア80898

answer CHANGED
@@ -1,4 +1,6 @@
1
1
  解決したいだけでしたら確認する点は二点です。
2
2
 
3
3
  0. キャスト(array)が邪魔
4
- 0. 配列の添え字で使うIDとidは別物。データベースの設定と合ってる?
4
+ 0. 配列の添え字で使うIDとidは別物。データベースの設定と合ってる?
5
+
6
+ **途中投稿してしまいました。追記中です。少々お待ちください。**