Invalid argument supplied for foreach()
PDOStatementクラスはそれ自体をforeach
で回せるので,無理にfetch()
やfetchAll()
メソッドを使わなくてもいいのですが,現在false
をforeachで回そうとしている状態です.ここにも条件分岐が必要です.
php
1$stmt = $pdo->query($sql);
2if (!$stmt) {
3 die('クエリが失敗'); // これが本当の「クエリが失敗」であって,最初のものは「接続が失敗」なのでエラーメッセージが不適切
4}
しかしこれでは何が悪いのかわからないため,根本的な解決にはなりません.そもそもPDOのコンストラクタでエラーモードを変更して,このような条件分岐を全て不必要にすべきです.全体的に書き方が微妙な感じなので,大きく書きなおしてみます.以下で言及していることを根拠とします.
html
1<?php
2
3$db_host = 'ホスト名';
4$db_name = 'データベース名';
5$db_user = 'ユーザー';
6$db_pass = 'パス';
7
8try {
9
10 // new PDO() の部分以外でもPDOExceptionが異常時に飛ぶように設定しながら接続
11 $pdo = new PDO("mysql:dbname=$db_name;host=$db_host;charset=utf8", $db_user, $db_pass, [
12 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
13 ]);
14
15 // 一気に全行2次元配列として取得
16 $rows = $pdo->query("SELECT * FROM テーブル名")->fetchAll(PDO::FETCH_ASSOC);
17
18} catch (PDOException $e) {
19
20 // 「500 Internal Server Error」にして,HTMLではなくテキストでエラーメッセージを表示して終了
21 header('Content-Type: text/plain; charset=UTF-8', true, 500);
22 exit($e->getMessge());
23
24}
25
26// テキストデータをHTML内に埋め込む際には必ずこの関数を通さなければならない
27function h($str)
28{
29 return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
30}
31
32?>
33<!DOCTYPE html>
34<meta charset="UTF-8">
35<title>Example</title>
36<?php if (empty($rows)): ?>
37<h1>データがありません</h1>
38<?php else: ?>
39<h1>データ一覧</h1>
40<table border="1">
41 <tr>
42<?php foreach ($rows[0] as $key => $_): ?>
43 <th><?=h($key)?></th>
44<?php endforeach; ?>
45 </tr>
46<?php foreach ($rows as $row): ?>
47 <tr>
48<?php foreach ($row as $value): ?>
49 <td><?=h($value)?></td>
50<?php endforeach; ?>
51 </tr>
52<?php endforeach; ?>
53</table>
54<?php endif; ?>
追記: 指定した1つのカラムにおける一意な値のみを1次元配列で選択するサンプル
html
1<?php
2
3$db_host = 'ホスト名';
4$db_name = 'データベース名';
5$db_user = 'ユーザー';
6$db_pass = 'パス';
7
8try {
9
10 // new PDO() の部分以外でもPDOExceptionが異常時に飛ぶように設定しながら接続
11 $pdo = new PDO("mysql:dbname=$db_name;host=$db_host;charset=utf8", $db_user, $db_pass, [
12 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
13 ]);
14
15 // 一気に全行1次元配列として取得
16 $values = $pdo->query("SELECT DISTINCT カラム名 FROM テーブル名")->fetchAll(PDO::FETCH_COLUMN);
17
18} catch (PDOException $e) {
19
20 // 「500 Internal Server Error」にして,HTMLではなくテキストでエラーメッセージを表示して終了
21 header('Content-Type: text/plain; charset=UTF-8', true, 500);
22 exit($e->getMessge());
23
24}
25
26// テキストデータをHTML内に埋め込む際には必ずこの関数を通さなければならない
27function h($str)
28{
29 return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
30}
31
32?>
33<!DOCTYPE html>
34<meta charset="UTF-8">
35<title>Example</title>
36<h1>データ一覧</h1>
37<ul>
38<?php foreach ($values as $value): ?>
39 <li><?=h($value)?></li>
40<?php endforeach; ?>
41</ul>