Joomla Select à partir du groupement DB AND / OR

Jan 26 2021

Je n'ai trouvé aucun guide sur la façon de gérer de telles requêtes dans Joomla:

Je voudrais sélectionner tous les éléments de db qui sont:

Published
AND
(the publish up date is 0000-00-00 00:00:00 or smaller then datenow)
OR
(the publish down date is 0000-00-00 00:00:00 or larger then datenow)

pour obtenir tous les éléments publiés et dont la date de début de publication est comprise dans la date de début / fin de publication ou lorsque les valeurs de début / fin définies ne sont pas définies.

Ce que j'ai jusqu'à présent est une simple requête:

$query->where($db->quoteName('published') . ' = 1 ');
$query->where($db->quoteName('publish_up') . ' = ' . $db->quote('0000-00-00 00:00:00')) ->orWhere($db->quoteName('publish_up') . '<' . $db->quote($date));
$query->where($db->quoteName('publish_down') . ' = ' . $db->quote('0000-00-00 00:00:00')) ->orWhere($db->quoteName('publish_down') . '>' . $db->quote($date));
        

Jusqu'ici tout va bien, mais à la fin, cela crée une requête comme celle-ci:

SELECT *
FROM `tblname`
WHERE 
(
(`published` = 1  AND `publish_up` = \'0000-00-00 00:00:00\') OR 
(`publish_up`<\'2021-01-26 13:03:07\') OR `publish_down` = \'0000-00-00 00:00:00\') OR 
(`publish_down`>\'2021-01-26 13:03:07\')
ORDER BY ordering ASC

Joomla ne définit ni ne regroupe la requête comme j'en ai besoin, le premier est ET, puis tout le reste est OU.

Je suis sûr que c'est juste un manque de connaissances / syntaxe plutôt qu'un bogue - mais comment est-ce que la bonne façon d'écrire une requête appropriée en fonction de mes besoins?

PS: la table DB provient d'un composant personnalisé

Réponses

2 mickmackusa Jan 27 2021 at 07:29

Parce que 0000-00-00 00:00:00sera toujours inférieur à l'horodatage actuel, je comprends vos besoins comme:

published = 1
AND
publish_up <= now
AND
(
    publish_down = 0000-00-00 00:00:00
    OR
    publish_down > now
)
  • where()a une valeur de collage par défaut de AND.
  • andWhere()a une valeur de collage par défaut de OR.

Pour traduire cela dans le générateur de requêtes de Joomla, vous écririez:

$query ->where( [ $db->quoteName('published') . ' = 1'),
            $db->quoteName('publish_up') . ' <= ' . $db->quote($date), ] ) ->andWhere( [ $db->quoteName('publish_down') . ' = ' . $db->quote('0000-00-00 00:00:00'), $db->quoteName('publish_down') . ' > ' . $db->quote($date)
        ]
    )

Votre logique requise s'aligne parfaitement sur les colles par défaut des méthodes, donc aucune déclaration de glue n'est nécessaire.

SQL rendu:

WHERE
(`published` = 1 AND `publish_up` <= '2021-01-26 13:03:07') AND
(`publish_down` = '0000-00-00 00:00:00' OR `publish_down` > '2021-01-26 13:03:07')

Remarques:

  1. Le chaînage ou le non chaînage des appels de méthode n'affecte pas la manière dont le SQL est généré. En d'autres termes, vous ne gagnez ni ne perdez aucune parenthèse en continuant ou en rompant une "chaîne" d'appels de méthode.

  2. J'utiliserais à CURRENT_TIMESTAMPmoins que vous ne soyez $datepas ce que je pense. Comme:

    $db->quoteName('publish_up') . ' <= CURRENT_TIMESTAMP',
    
  3. Voici un autre de mes articles qui explore différentes combinaisons de syntaxe de construction where .