Joomla Seleziona da DB AND / OR raggruppamento

Jan 26 2021

Non ho trovato alcuna guida su come gestire tali query in Joomla:

Vorrei selezionare tutti gli elementi da db che sono:

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)

per ottenere tutti gli elementi pubblicati e datenow rientra nella data di inizio / fine pubblicazione o quando i valori di inizio / fine impostati non sono impostati.

Quello che ho finora è una semplice domanda:

$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));
        

Fin qui tutto bene, ma alla fine crea una query in questo modo:

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 non imposta o raggruppa la query come ne ho bisogno, la prima è AND e poi tutto il resto è OR.

Sono sicuro che è solo un divario di conoscenza / sintassi piuttosto che un bug, ma come è il modo corretto di scrivere una query corretta in base alle mie esigenze?

PS: la tabella DB proviene da un componente personalizzato

Risposte

2 mickmackusa Jan 27 2021 at 07:29

Poiché 0000-00-00 00:00:00sarà sempre inferiore all'attuale data / ora, comprendo le tue esigenze come:

published = 1
AND
publish_up <= now
AND
(
    publish_down = 0000-00-00 00:00:00
    OR
    publish_down > now
)
  • where()ha un valore di colla predefinito di AND.
  • andWhere()ha un valore di colla predefinito di OR.

Per tradurlo nel querybuilder di Joomla dovresti scrivere:

$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)
        ]
    )

La logica richiesta è perfettamente allineata con i collanti predefiniti dei metodi, quindi non sono necessarie dichiarazioni di colla.

SQL renderizzato:

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

Appunti:

  1. Il concatenamento o il mancato concatenamento delle chiamate al metodo non influisce sul modo in cui viene generato sql. In altre parole, non si guadagna o si perde alcuna parentesi continuando o interrompendo una "catena" di chiamate di metodo.

  2. Lo userei a CURRENT_TIMESTAMPmeno che il tuo $datenon sia quello che penso che sia. Piace:

    $db->quoteName('publish_up') . ' <= CURRENT_TIMESTAMP',
    
  3. Ecco un altro dei miei post che approfondisce diverse combinazioni di dove si costruisce la sintassi .