web-dev-qa-db-ja.com

2つの条件を持つWHERE句を使用してクエリを作成する方法

このselectステートメントをWHERE条件で機能させることができないようです。データのロード方法に応じて、最初のテスト結果またはすべてのテスト結果を取得しますが、希望するuser_id固有の結果は取得しません。

私は何度もドキュメントを調べましたが、これは簡単なことですが、何が起こっているのか理解できません。 getUser()関数を個別にチェックしましたが、正常に動作しています。test_id条件が機能していないようです。

$db = JFactory::getDbo();
$user = JFactory::getUser();
$query = $db->getQuery(true);

$query -> SELECT('Test_Percentile');
$query -> FROM($db->quoteName('#__calc_results'));
$query -> WHERE(($db->quoteName('test_id').'='.'1')AND($db- 
>quoteName('user_id').'='.($user->id)));

$db->setQuery($query);
$result = $db->loadObject();

echo "<p>" . $result->Test_Percentile ."</p>";
1
BabyCode123

これを試して:

$query->WHERE($db->quoteName('test_id').'= 1 AND '.$db->quoteName('user_id').'='. $user->id)
2
Terry Carter

何が問題になっていますか?

ANDで区切られた2つの条件を含む有効な式を誤って作成しました。

_($db->quoteName('test_id').'='.'1')AND($db->quoteName('user_id').'='.($user->id))
_

次のすべてと同じです:( Demo

_("`test_id`=1")AND("`user_id`=$user->id")
"`test_id`=1" && "`user_id`=$user->id"
true && true
true
_

ブールtrueを文字列に変換すると、_1_になります。

問題を調査する方法は?

System>Global Configurationに移動すると、生成された_1_が表示され、システムタブのデバッグ設定セクションで、デバッグシステムフィールドをはい。次に、スクリプトをリロードし、ページの下部にあるデータベースクエリボックスをクリックして、実行されたすべてのクエリを表示し、クエリが見つかるまで下にスクロールします。ここにあなたが見るものがあります:

SELECT Test_Percentile FROM _[prefix]_calc_results_ WHERE 1

生成されたクエリが希望どおりではない場合、返された行の数がデータベーステーブルのすべての行になることもわかります。これは、_WHERE 1_が効果的に何も除外しないためです。 PHPコードで$db->loadObject()を使用しているため、結果セットですべての行が配信されているにもかかわらず、最初の行だけがアクセスされて表示されます。

いくつかのベストプラクティスの提案:

クエリ構文を修正するだけでなく、コードをクリーンで読みやすく、効率的で、デバッグしやすい状態に保つのに役立つ、将来の開発プロジェクトに適用するために、他にもいくつかの改良をお勧めします。

  1. _$query_の最初の宣言から「チェーン」を使用します。つまり、_->_を使用して、各行に_$query_を書き込む代わりに、_$query_にすべて適用されるメソッド呼び出しを接続します。
  2. 小文字のメソッド呼び出しを使用して、Joomlaのドキュメントの表示内容をミラーリングします。
  3. クエリを有効にするために、テーブル名や列名でバックティックラッピングを使用する必要がないため、コードの肥大化を回避し、これらの呼び出しを省略できます。 quoteName()quote()の呼び出しを多数行ってもコードに害はありませんが、コードはより簡潔になるため、これらを使用しなくても読みやすくなります。
  4. $query->dump()を使用して、生成されたクエリが意図したとおりのものであることを確認します。
  5. 結果セットの最初の行から単一の列にのみアクセスする場合は、loadResult()を使用します。
  6. 結果セットに行が返されなかったかどうかを確認すると便利な場合があります。 _!_を使用して「誤った」結果を確認する(同じ手順で結果の値を宣言して確認する以下のスニペットを参照)は、多くの場合、賢明なインクルードです。
  7. _try{}catch{}_ブロックの使用は、コードをデバッグするための迅速で簡単な方法です(グローバルエラーレポートをオンにし、スクロールしてスクロールし、実際にデバッグしようとしているクエリを見つける必要があるのと比較して)。 JFactory::getApplication()->enqueueMessage()は、診断情報とエラー情報をパッケージ化する優れた方法です。これは、ページの上部のbootstrapメッセージボックスに表示されるためです。

私の推奨スニペット:

_try {
    $db = JFactory::getDbo();
    $user = JFactory::getUser();
    $query = $db->getQuery(true)
                ->select("Test_Percentile")
                ->from("#__calc_results")
                ->where("test_id = 1 AND user_id = $user->id");
    $db->setQuery($query);
    JFactory::getApplication()->enqueueMessage($query->dump(), 'info');
    if (!$perc = $db->loadResult()) {
        echo "<p>No Rows Found</p>";
    } else {
        echo "<p>$perc</p>";
    }
} catch (Exception $e) {
    JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');
}
_

適切なセキュリティ慣行の問題として、クエリやエラーメッセージを公開しないでください

WHERE句を作成する別の方法:

真実は、Joomlaのクエリビルダーメソッドを使用して2つの条件を含む有効なWHERE句を記述する方法がいくつかあることです(上記の完全な有効な単一の文字列以外)。

where() x2:

_->where("test_id = 1")
->where("user_id = $user->id");
// WHERE test_id = 1 AND user_id = 75
_

where()およびandWhere():(不要な括弧はお勧めしません)

_->where("test_id = 1")
->andWhere("user_id = $user->id");
// WHERE (test_id = 1) AND (user_id = 75)
_

where()条件の配列:

_->where(array("test_id = 1", "user_id = $user->id"));
// WHERE test_id = 1 AND user_id = 75
_
1
mickmackusa