質問: null; echo 'DB切断成功'; ?> ``` ### 試したこと 接続の有無等は確認し、下記のように表示されるようになっています。 --- 接続成功1接続成功2 DB切断成功 --- ですが、肝心のDBから取得した値がとれず...。 phpMyAdmin自体をあまり理解できていないため そこが原因なのか?とも考えているのですが phpも初心者なので、原因の切り分けもできず...。 分からないことが分からない状態ですので、教えていただければと思います...。 ### 補足情報(FW/ツールのバージョンなど) DB・サーバーは、エックスサーバの無料のものを使用しています。 MySQLバージョン 5.0.95 WordPressバージョン: 5.0.3 PHPバージョン:PHP7.0.x
回答: DBに接続する際には下記のような記事が参考になります。 * PHPでデータベースに接続するときのまとめ ですが、 解決したいだけでしたら確認する点は二点です。 1. キャスト(array)が邪魔 2. 配列の添え字で使うIDとidは別物。データベースの設定と合ってる? 1.キャスト(array)が邪魔について ==================== PDO::queryの返却値は「PDOStatement オブジェクト」OR「false」です。 つまり、返却値を確認してfalseでなければ、一応、queryは無事届けられたと思って良いです。 try-catchを随所に書かれていますが、それは**プログラムが必ず成功するわけではないという前提**で書かれているもののはずです。 で、あれば、そのqueryも**必ず成功するわけではないという前提**で対応しましょう。 ``` if(!$stmt){ die('失敗'); } //成功したときの処理 ``` もちろん、デバッグのために$stmtが何をもっているか確認するのは必須です。 ``` var_dump($stmt); if(!$stmt){ die('失敗'); } //成功したときの処理 ``` ※確認できたらいったん行頭に//をつけてコメントアウトしておくと良いです。 これでvar_dump()の結果が `object(PDOStatement)#3 (1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }` のように返ってきていたら成功しています。 もし、`bool(false)` とだけ出ていたら失敗しています。 ここで1点アドバイス。 今のコーディング内容ではPDOExceptionをちゃんと拾うようにできていません。 `new PDO()`する際に幾つか引数をつけて実行していると思いますが PDOの引数、今のところは$dsn,$username,$passwordまでしか入れてませんよね? その次の$optionに注目してください。 > > ドライバ固有の接続オプションを指定するキー=> 値の配列。 > > > ここで色々なOPTIONを指定することができますが、その中にATTR_ERRMODEというのがあります。(属性の説明) ここでPDO::ERRMODE_EXCEPTIONを指定することできちんとExceptionを拾うようになります。 最初に提示したQiitaの参考記事では下記のように$optionsを指定していますね。 ``` [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, ] ``` 上記をPDO()接続時の引数に指定した上でもう一度実行してみてください。 そこで`エラーSQLSTATE[・・・・`のようなエラーメッセージが出てきたらその先のエラーコードとエラー理由を確認しましょう。 参考:エラーメッセージの読み方と対処, 検索や質問の原則 出ていないのでしたらようやく「キャスト(array)が邪魔」の対応ができます。 出ていない=queryはきちんと届けられていて成功している わけですが キャストをしてしまうことで変数の型が変わります。 foreachの前でこうしてみましょう。 ``` var_dump((array)$stmt); ``` 結果は下記のようになっていませんか? `array(1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }` PDO::queryで折角取得できたPDOStatementがなくなってしまっています。 つまり、SELECT文の実行結果は「結果セット」つまり、データが入っているとイコールなので、そこがなくなってしまうと 実行結果もなくなってしまうということになります。 実行結果をそのまま素直にループさせれば良いです。 ``` foreach ($stmt as $row) { // 出力 echo $row['ID']; } ``` キャストを含めたコーディングで注意すべき点は下記のような記事が参考になります。 * 初心者を戒めるPHP * モダンPHPアンチパターン foreach()には配列とオブジェクトのみ使えますが、 何が入っているか確かめていない配列を(array)でキャストすることによって 無理やりコードを正常化してしまっていることになります。 つまり、気づけたはずのエラーが気づけなくなるわけです。 これに限らずキャストが必要な場面はほとんどありません。 キャストするくらいなら変数が想定の情報を持ってきているかを確認した上で実行するように組んでください。 2.配列の添え字で使うIDとidは別物。データベースの設定と合ってる? について ======================================== これに加えてもう1つ確認すべき点があります。 一応(array)キャストをすることで下記のような配列ができるのでforeachはできるはず。 `array(1) { ["queryString"]=> string(XX) "SELECT ID FROM TB_LIST" }` コードでは`$row['ID']`を参照しようとしていますが、そのようなデータありません。 連想配列そのまま回しているので$rowだけで`SELECT ID FROM TB_LIST`が取れるはず。 PHPにおいて、存在しないキーを参照しようとすると`Warning: Illegal string offset '指定名'`または`Notice: Undefined index`のようなエラーが出ます。 ※きちんとケースはありますが、どちらかが出てたら参照が間違っているという理解でいたらいいです おそらく質問者さんの実行環境ではエラー表示が制御されているのではないでしょうか。 学習段階、開発途中段階のコードでは何が起きるか分からないので、全てのレベルのエラー表示をするようにしておくことを強くすすめます。 * エラー表示ON 1.を全て対応した後でも想定通りの結果が出ない場合はここまでやってみてください。 配列の添え字のキーを間違えていないか?大文字と小文字は別物です。 ``` $hoge["a"] = "hello"; echo $hoge["d"]; // Notice: Undefined index: A echo $hoge["A"]; // Notice: Undefined index: A echo $hoge["a"]; // Hello ``` 以下、今後を見据えた場合の蛇足。 1. データを出力するときはHTMLエスケープをしよう。 なぜそうすべきかというのはXSSとかで調べると良いです。 2. 今後、もしかしたら検索条件などを指定してデータを取得する機会があるかもしれませんが、そのときはSQLのエスケープは必ず行おう。PDO::queryよりもPDO::prepareで「プリペアドステートメント」をセットしてからのbindValueがおすすめです。 なぜそうすべきかはSQLインジェクションとかで調べると良いです。 以上。