1. ホーム
  2. php

[解決済み] mysqli_fetch_array() を使用します。引数 #1 は mysqli_result 型でなければなりません。mysqliの問題に対処するには?

2022-05-18 06:47:36

質問

ローカル/開発環境では、MySQLi クエリは問題なく実行されています。しかし、それを Web ホスト環境にアップロードすると、このエラーが表示されます。

致命的なエラーです。メンバ関数bind_param()の呼び出しがオブジェクト以外であり、かつ...

以下はそのコードです。

global $mysqli;
$stmt = $mysqli->prepare("SELECT id, description FROM tbl_page_answer_category WHERE cur_own_id = ?");
$stmt->bind_param('i', $cur_id);
$stmt->execute();
$stmt->bind_result($uid, $desc);

クエリを確認するために、コントロールパネルからクエリを実行してみました。 phpMyAdmin を実行してみましたが、結果はOKでした。

どのように解決するのですか?

TL;DR

  1. 常に mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); を必ず記述してください。これは MySQL に、クエリ、サーバ、データベースなど、実際の問題が何であるかを知らせます。
  2. SQL クエリ内のすべての PHP 変数を常にクエスチョンマークに置き換え、そのクエリを プリペアドステートメント . あらゆる種類の構文エラーを回避するのに役立ちます。

説明

MySQLi のコードで、次のようなエラーが発生することがあります。 mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given... , Call to a member function bind_param()... といった具合です。または、エラーがなくても、クエリがすべてうまくいかない。それは、クエリの実行に失敗したことを意味します。

クエリが失敗するたびに、MySQLは のエラーメッセージが表示され、その理由を説明します。 . 残念ながら、デフォルトではそのようなエラーはPHPに転送されず、上記のような不可解なエラーメッセージしか得られない。 したがって、MySQL のエラーを報告するように PHP と MySQLi を設定することが非常に重要です。そして、一度エラーメッセージを取得すれば、それを修正するのは簡単なことです。

MySQLiでエラーメッセージを取得する方法

まず最初に、MySQLiの接続の前に必ずこの行を入れてください。 全て の前に記述してください。

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

その後、すべてのMySQLエラーはPHPの例外に転送されます。捕捉されない例外は、今度は、PHP の致命的なエラーになります。したがって、MySQL エラーの場合、従来の PHP エラーが表示されます。これにより、エラーの原因を即座に認識することができます。そして、スタックトレースは、エラーが発生した正確な場所に導いてくれます。

異なる環境でPHPを設定する方法

以下は、私が書いた記事の要点です。 PHP のエラー報告 : 開発用サーバーと本番用サーバーでは、エラーの報告方法を変えなければなりません。開発サーバーでは、エラーが画面に表示されるのは便利ですが、本番サーバーでは、エラーメッセージは代わりに記録されなければならず、後でエラーログでそれらを見つけることができます。

したがって、対応する設定オプションを以下の値に設定する必要があります。

  • 開発サーバーの場合

  • error_reporting を設定する必要があります。 E_ALL の値で指定します。

  • log_errors は1にしてください(開発用PCにもログがあると便利です)。

  • display_errors は 1 に設定する必要があります。

  • 本番サーバーでは

  • error_reporting を設定する必要があります。 E_ALL の値で指定します。

  • log_errors は 1 に設定する必要があります。

  • display_errors は0に設定する必要があります。

実際の使用方法

手動でエラーをチェックするコードを削除すればよい は、すべてのこれらの or die() , if ($result) といった具合です。データベースとのインタラクションコードをすぐに書くことができます。

$stmt = $this->con->prepare("INSERT INTO table(name, quantity) VALUES (?,?)");
$stmt->bind_param("si", $name, $quantity);
$stmt->execute();

もう一度 の周りに何の条件もなく . エラーが発生した場合、それはあなたのコードにおける他のエラーと同様に扱われます。たとえば、開発用 PC では画面に表示されるだけですが、ライブサイトではプログラマのためにログが記録され、ユーザの利便性のためにエラーハンドラを使用することができます(ただし、これは MySQLi の話題とは別の話ですが、上記のリンク先の記事で読むことができます)。

表示されたエラーメッセージをどうするか

まず最初に、問題のクエリを特定する必要があります。エラーメッセージには ファイル名と行番号 が含まれています。単純なコードであればこれで十分ですが、関数やクラスを使っているコードでは スタックトレース を実行して、問題のあるクエリを探します。

エラーメッセージを取得したら、それを読んで理解する必要があります。慇懃無礼とまではいかないまでも、あまりにも当然のことのように聞こえますが、学習者はエラーメッセージが単なるアラーム信号ではなく、実際には 問題の詳細な説明 . そして、必要なのは、エラーメッセージを読んで問題を解決することです。

  • 例えば、特定のテーブルが存在しないと書かれていたら、スペル、タイプミス、文字のケースをチェックする必要があります。また、PHP スクリプトが正しいデータベースに接続していることを確認する必要があります。
  • あるいは、SQL 構文にエラーがあると表示された場合、SQL を調べなければなりません。そして問題箇所は、右の の前です。 の直前で、エラーメッセージに引用されているクエリ部分です。

エラーメッセージが理解できない場合は、ググってみてください。そして、その結果を見るときは、以下のような回答にこだわること。 を説明する のある回答にこだわることです。解決策はあなたの特定のケースでは機能しないかもしれませんが、説明は問題を理解するのに役立ち、自分で問題を解決できるようになるのです。

また 信頼 を信頼する必要があります。もしトークンの数が束縛された変数の数と一致しないというのであれば、それは ということです。テーブルやカラムがない場合も同様です。あなた自身のミスであろうと、エラーメッセージが間違っていようと、選択肢があるのなら、常に前者にこだわってください。繰り返しになりますが、見下したように聞こえるかもしれませんが、まさにこのサイトの何百もの質問が、このアドバイスが非常に有用であることを証明しています。

エラー報告に関して絶対にやってはいけないことのリスト

  • エラー抑制演算子( @ )! プログラマがエラーメッセージを読めなくなり、エラーを修正できなくなります。
  • を使用しないでください。 die() または echo などの関数で、無条件にエラーメッセージを画面に表示させることができます。PHPはそれ自体でエラーを報告することができ、正しい方法でそれを行うことは環境に依存します - だから、PHPのためにそれを残しておいてください。
  • クエリの結果をテストするための条件を手動で追加しないでください (たとえば if($result) ). エラー例外を有効にすると、そのような条件は単に無意味になります。
  • を使用しないでください。 try..catch 演算子は使わないでください。この演算子は、トランザクションのロールバックのようなエラー処理を行うために使用すべきです。しかし、エラーを報告するためだけに使ってはいけません。上で学んだように、PHP はすでに正しい方法でそれを行うことができます。

追伸

エラーは出ないけど、結果も出ないということがあります。ならば、それはつまり 条件に一致するデータがデータベース内にない . この場合、たとえデータと条件に問題がないと誓うことができたとしても、この事実を認めなければなりません。そうではありません。もう一度確認する必要があります。

この問題に役立つ記事があります。 データベースのインタラクションをデバッグする方法 . これは PDO 用に書かれたものですが、原理は同じです。これらの指示に順を追って従うだけで、問題が解決するか、Stack Overflowに答えられる質問ができるようになります。