Joomla Wybierz z grupowania DB AND / OR

Jan 26 2021

Nie znalazłem poradnika jak obsłużyć takie zapytania w Joomla:

Chciałbym zaznaczyć wszystkie pozycje z db, które są:

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)

aby pobrać wszystkie opublikowane elementy, a dataenow przypada w ramach daty rozpoczęcia / zakończenia publikacji lub gdy ustawione wartości początkowe / końcowe nie są ustawione.

Do tej pory mam proste zapytanie:

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

Jak na razie dobrze, ale ostatecznie tworzy zapytanie takie:

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 nie ustawia ani nie grupuje zapytania tak, jak tego potrzebuję, pierwsze to AND, a wszystko inne to OR.

Jestem pewien, że to tylko luka wiedzy / składni, a nie błąd - ale jaki jest prawidłowy sposób pisania odpowiedniego zapytania w oparciu o moje potrzeby?

PS: tabela DB pochodzi z komponentu niestandardowego

Odpowiedzi

2 mickmackusa Jan 27 2021 at 07:29

Ponieważ 0000-00-00 00:00:00zawsze będzie mniejsza niż aktualna data i godzina, twoje wymagania rozumiem jako:

published = 1
AND
publish_up <= now
AND
(
    publish_down = 0000-00-00 00:00:00
    OR
    publish_down > now
)
  • where()ma domyślną wartość kleju AND.
  • andWhere()ma domyślną wartość kleju OR.

Aby przetłumaczyć to na program do tworzenia zapytań Joomla, napisałbyś:

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

Twoja wymagana logika doskonale zgadza się z domyślnymi klejami metod, więc deklaracje kleju nie są konieczne.

Renderowany SQL:

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

Uwagi:

  1. Łączenie wywołań metod w łańcuch lub nie ma wpływu na sposób generowania kodu sql. Innymi słowy, nie zyskujesz ani nie tracisz żadnych nawiasów w wyniku kontynuowania lub przerywania „łańcucha” wywołań metod.

  2. Używałbym, CURRENT_TIMESTAMPchyba że twój $datenie jest tym, czym myślę, że jest. Lubić:

    $db->quoteName('publish_up') . ' <= CURRENT_TIMESTAMP',
    
  3. Oto kolejny z moich postów, który zagłębia się w różne kombinacje miejsc budowania składni .