web-dev-qa-db-fra.com

Comment écrire une requête avec une clause WHERE avec deux conditions?

Je n'arrive pas à faire en sorte que cette instruction select fonctionne avec les conditions WHERE. En fonction de la manière dont les données sont chargées, je reçois le premier résultat du test ou tous les résultats du test et non le résultat spécifique à l’utilisateur id-utilisateur que je souhaite.

J'ai parcouru la documentation encore et encore et je sais que c'est simple, mais je ne peux pas comprendre ce qui se passe. J'ai vérifié séparément la fonction getUser() et elle fonctionne bien, la fonction test_id la condition ne semble pas fonctionner.

$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

Essaye ça:

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

Qu'est-ce qui ne va pas?

Vous avez involontairement formé une expression valide contenant deux conditions élémentaires séparées par AND.

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

est identique à tout ce qui suit: ( Demo )

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

Lorsque vous convertissez le booléen true en chaîne, il devient 1.

Comment enquêter sur votre problème?

Vous pouvez voir le 1 Généré si vous allez dans Système > Configuration globale , puis sous l'onglet Système , dans les paramètres de débogage , définissez le champ Système de débogage sur Oui . Rechargez ensuite votre script. Au bas de votre page, cliquez sur la case Requêtes de la base de données pour afficher toutes les requêtes exécutées, puis faites défiler l'écran jusqu'à trouver votre question. Voici ce que vous verriez:

SELECT Test_Percentile FROM [prefix]_calc_results WHERE 1

Au-delà de la requête générée n'étant pas ce que vous désirez, vous verrez également que le nombre de lignes renvoyées correspondra à toutes les lignes de votre table de base de données, car WHERE 1 Ne filtre rien. Vous utilisez $db->loadObject() dans votre code php. Ainsi, malgré toutes les lignes livrées dans le jeu de résultats, seule la première ligne est accessible et affichée.

Quelques suggestions de meilleures pratiques:

Au-delà de la correction de la syntaxe de votre requête, j'aimerais vous recommander un certain nombre d'améliorations à appliquer à vos projets de développement futurs, ce qui vous aidera à garder votre code propre, lisible, efficace et facile à déboguer.

  1. Utilisez "chaînage" à partir de votre première déclaration de $query. Cela signifie que vous devez utiliser -> Pour connecter vos appels de méthode qui s'appliquent tous à $query Au lieu d'écrire $query Sur chaque ligne.
  2. Utilisez des appels de méthode en minuscule pour refléter ce que la documentation Joomla affiche.
  3. Étant donné qu'aucune de vos tables ou noms de colonne ne nécessite l'utilisation de backtick-wrapping pour rendre la requête valide, vous pouvez éviter le code et éviter ces appels. Votre code ne fait certainement pas de mal à faire une série d'appels quoteName() et quote(), mais votre code sera plus bref et donc plus facile à lire sans eux.
  4. Utilisez $query->dump() pour vérifier que la requête générée correspond exactement à ce que vous souhaitez créer.
  5. Utilisez loadResult() lorsque vous ne souhaitez accéder qu'à une seule colonne de la première ligne d'un jeu de résultats.
  6. Il est souvent utile de vérifier si aucune ligne n'a été renvoyée dans le jeu de résultats. Rechercher un résultat "falsey" avec ! (Voir l'extrait ci-dessous où je déclare et vérifie la valeur du résultat dans la même étape) est souvent une inclusion judicieuse.
  7. L'utilisation d'un bloc try{}catch{} Est un moyen simple et rapide de déboguer votre code (par rapport à l'activation du rapport d'erreur global et au défilement pour trouver la requête que vous essayez de déboguer). JFactory::getApplication()->enqueueMessage() est un excellent moyen de regrouper les informations de diagnostic et d'erreur, car il les affiche en haut de votre page dans une boîte de message bootstrap).

Mon extrait recommandé:

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');
}

Il serait négligent de ma part de ne pas mentionner: Vous ne devez jamais afficher de requêtes ou de messages d'erreur au public, afin de respecter les règles de sécurité

Autres moyens de construire la clause WHERE:

En réalité, il existe plusieurs façons d'écrire une clause WHERE valide qui contient deux conditions avec la méthode du générateur de requêtes de Joomla (au-delà de la chaîne unique valide parfaite ci-dessus).

where() x2:

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

where() et andWhere(): (je ne conseille pas les parenthèses inutiles)

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

where() avec un tableau de conditions:

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