Joomla Select à partir du groupement DB AND / OR
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
Parce que 0000-00-00 00:00:00
sera 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 deAND
.andWhere()
a une valeur de collage par défaut deOR
.
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:
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.
J'utiliserais à
CURRENT_TIMESTAMP
moins que vous ne soyez$date
pas ce que je pense. Comme:$db->quoteName('publish_up') . ' <= CURRENT_TIMESTAMP',
Voici un autre de mes articles qui explore différentes combinaisons de syntaxe de construction where .