PHPとMySQLにおける「mysql_fetch_array()/mysql_fetch_assoc()/mysql_fetch_row()/mysql_num_rows etc... expects parameter 1 to be resource」エラーの原因と解決策
PHPとMySQLにおける「mysql_fetch_array()/mysql_fetch_assoc()/mysql_fetch_row()/mysql_num_rows etc... expects parameter 1 to be resource」エラーの原因と解決策
上記のエラーメッセージは、PHPのMySQL拡張機能でmysql_fetch_array()
、mysql_fetch_assoc()
、mysql_fetch_row()
、mysql_num_rows()
などの関数を呼び出す際に、最初の引数に渡されるべきリソース変数が不正な場合に発生します。
原因
このエラーが発生する主な原因は以下の3つです。
- mysql_query()関数が失敗している
mysql_query()
関数が失敗した場合、FALSEが返されます。このFALSEをmysql_fetch_array()
などの関数に渡すと、上記のエラーが発生します。
- リソース変数が破損している
mysql_query()
関数が成功しても、リソース変数が破損している場合、上記のエラーが発生します。
- mysql_fetch_array()などの関数の引数に誤りがある
解決策
以下の対策を試してください。
mysql_query()
関数が成功したかどうかを確認するには、mysql_error()
関数を使用してエラーメッセージを取得します。
$result = mysql_query("SELECT * FROM users");
if ($result === FALSE) {
echo mysql_error() . PHP_EOL;
exit;
}
mysql_fetch_array()
などの関数の引数には、mysql_query()
関数によって返されるリソース変数を渡す必要があります。
$result = mysql_query("SELECT * FROM users");
while ($row = mysql_fetch_array($result)) {
echo $row['username'] . PHP_EOL;
}
- MySQL拡張機能の代わりにPDOを使用する
MySQL拡張機能は非推奨となっており、将来的に削除される予定です。代わりにPDOを使用することを推奨します。
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->prepare("SELECT * FROM users");
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['username'] . PHP_EOL;
}
<?php
// データベース接続
$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
// SQLクエリ実行
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindValue(':username', 'taro');
$stmt->execute();
// 結果取得
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['username'] . PHP_EOL;
echo $row['email'] . PHP_EOL;
}
// データベース接続解除
$db = null;
?>
ポイント
- データベース接続にはPDOを使用しています。
- SQLクエリにはプレースホルダを使用し、バインド変数で値を代入しています。
- 結果取得には
PDO::FETCH_ASSOC
を使用し、連想配列でデータを取得しています。
- エラー処理を追加する
- 入力値のバリデーションを行う
- 接続情報は環境に合わせて変更する
他の方法
MySQL拡張機能の代わりにmysqli拡張機能を使用することもできます。
<?php
// データベース接続
$mysqli = new mysqli('localhost', 'root', '', 'test');
// SQLクエリ実行
$result = $mysqli->query("SELECT * FROM users WHERE username = 'taro'");
// 結果取得
while ($row = $result->fetch_assoc()) {
echo $row['username'] . PHP_EOL;
echo $row['email'] . PHP_EOL;
}
// データベース接続解除
$mysqli->close();
?>
PDOStatement::fetchAll()
メソッドを使用して、すべての結果を一度に取得することもできます。
<?php
// データベース接続
$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
// SQLクエリ実行
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindValue(':username', 'taro');
$stmt->execute();
// 結果取得
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
echo $row['username'] . PHP_EOL;
echo $row['email'] . PHP_EOL;
}
// データベース接続解除
$db = null;
?>
ジェネレータを使用して、結果を逐次的に取得することもできます。
<?php
function fetch_users($db, $username) {
$stmt = $db->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindValue(':username', $username);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
yield $row;
}
}
// データベース接続
$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
// 結果取得
foreach (fetch_users($db, 'taro') as $row) {
echo $row['username'] . PHP_EOL;
echo $row['email'] . PHP_EOL;
}
// データベース接続解除
$db = null;
?>
php mysql