みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

PHPでの検索機能実装について(フレームワーク無し

PHP初心者です。

現在、PHPにてDBからアクセスし、DBの検索を実装するプログラムを作成しております。
参考HPを元に下記のプログラムを作成したのですが、参考HPのコードではフレームワークが組み込まれており、
フレームワークを組んでいない私のコードではエラーが発生してしまいます。

エラー内容:
Warning: mysql_fetch_array() expects parameter 1 to be resource, (省略) line63
Warning: mysql_free_result() expects parameter 1 to be resource, (省略) line74

参考HPでは、search.phpの17行目'$search'が宣言されてない状態で記載されて
おりましたので、search.phpの最初にて宣言しました($searchでは検索キーを格納して
おります)。

恐れいりますが、ご教示願います。

input.php 検索ワードを送信
<form action="search.php" method="POST">
<input type="text" name="searchkey">
<input type="submit" name="searchid" value="検索">
</form>

search.php
<?php
$search = htmlspecialchars($_POST['searchkey']);

//データベースに接続
if (!$con = mysql_connect("ホスト名", "user名", "パスワード")) {
echo "接続エラー";
exit ;
}

//データベースを選択
if (!mysql_select_db("db名", $con)) {
echo "データベース選択エラー";
exit ;
}

//フォームで送られてきた条件を元にSELECT文を作成
$sql = "SELECT * FROM listwhere name LIKE '% . $search . %'";

//SELECT文を実行
if ($res = mysql_query($sql)) {
echo "SQLエラー<BR>" ;
exit ;
}
//検索結果<br>
echo "<table border=1>" ;
while($row = mysql_fetch_array($res)){ //エラー
echo "<tr>" ;
echo "<td>" . $row["id"] . "</td>" ;
echo "<td>" . $row["name"] . "</td>" ;
echo "<td>" . $row["date"] . "</td>" ;
echo "<td>" . $row["registant"] . "</td>" ;
echo "<td>" . $row["comment"] . "</td>" ;
echo "</tr>" ;
}
echo "</table>" ;
//結果セットの開放
mysql_free_result($res); //エラー
//データベースから切断
mysql_close($con);
?>

投稿日時 - 2013-10-02 19:47:42

QNo.8288963

困ってます

質問者が選んだベストアンサー

>> エラー内容:
>> Warning: mysql_fetch_array() expects parameter 1 to be resource, (省略) line63
>> Warning: mysql_free_result() expects parameter 1 to be resource, (省略) line74

どうしてこれを見て

>> フレームワークを組んでいない私のコードではエラーが発生してしまいます。

フレームワークが無いことが原因だと思ったのでしょうか?

//SELECT文を実行
if ($res = mysql_query($sql)) {
echo "SQLエラー<BR>" ;
exit ;
}

じゃなくて

//SELECT文を実行
if (!$res = mysql_query($sql)) {
echo "SQLエラー<BR>" ;
exit ;
}

が正しいです。もとのコードだと逆に実行に成功した場合にエラーとして処理してしまいます。

他にもダメ出しさせていただくと、

【セキュリティ的に危険なので今すぐにでも書き直すべき点】

1.
$search = htmlspecialchars($_POST['searchkey']);
また第2引数にENT_QUOTESを指定するならば効果はあるかもしれませんが、このままだと完全にエスケープ処理としては無意味です。シングルクオーテーションの入力をそのまま受け付けてしまい、「SQLインジェクション」攻撃の標的にされます。mysql関数を使った実装にするならば、mysql_real_escape_string関数を通す必要があります。
http://php.net/manual/ja/function.mysql-real-escape-string.php


【出来ればどうにかしたほうがいい点】

1.
いきなりスーパーグローバル変数のインデックスにアクセスすると、それが定義されてなかった場合にE_NOTICE、場合によってはE_WARNINGも発生してしまいます。下記リンクを参考に、最低限isset構造を使ってインデックスがセットされているか、手を抜きたくないならばその型が期待する「文字列型」であるかどうかをis_string関数を使ってチェックするようにしてください。
http://qiita.com/mpyw/items/2f9955db1c02eeef43ea
http://qiita.com/mpyw/items/c39b9ee695a5c2e74627

2.
mysql関数は非推奨です。上記でmysql_real_escape_string関数でエスケープすべきと述べましたが、そもそもmysql_connect関数からして使うべきではありません。下記リンクを参考にPDOで書き直してみてください。
http://qiita.com/mpyw/items/b00b72c5c95aac573b71

3.
LIKE検索をするには、SQL文としてのエスケープとは別にLIKE検索クエリ用のエスケープが必要です。addcslashes関数を使って、SQL文としてエスケープを行う前のパラメータに対し、「%」「_」「\」をエスケープしなければなりません。
http://www.phppro.jp/qa/4133#15296

4.
参考にしているHPが非常に古いと思われるので決して情報を鵜呑みにしないように。

投稿日時 - 2013-10-02 21:24:16

お礼

To_aru_Userさん
ご連絡頂きまして有難うございます。

丁寧かつ詳細なご教示のおかげで大変分かりやく、理解することができました。

また、参考HPでは$searchが宣言されてないにも関わらず、$sql = "SELECT * FROM listwhere name LIKE '% . $search . %'";と宣言されていたことから、フレームワークにて定義されているのではないかと判断した次第でございます。

今すぐにでも書き直すべき点と、出来ればどうにかしたほうがいい点も取り入れて作成していきたいと思います。

有難うございました。

投稿日時 - 2013-10-03 07:27:57

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(1)

あなたにオススメの質問