Joomla Выбор из БД И / ИЛИ группировки

Jan 26 2021

Я не нашел руководства, как обрабатывать такие запросы в Joomla:

Я хотел бы выбрать все элементы из базы данных, а именно:

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)

чтобы получить все опубликованные элементы, и datenow находится в пределах даты начала / окончания публикации или когда заданные значения начала / окончания не установлены.

Пока что у меня есть простой запрос:

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

Пока все хорошо, но в итоге он создает такой запрос:

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 не устанавливает и не группирует запрос по мере необходимости, сначала И, а затем все остальное ИЛИ.

Я уверен, что это просто пробел в знаниях / синтаксисе, а не ошибка, но как правильно написать правильный запрос, основанный на моих потребностях?

PS: таблица БД из пользовательского компонента

Ответы

2 mickmackusa Jan 27 2021 at 07:29

Поскольку 0000-00-00 00:00:00всегда будет меньше текущей отметки даты и времени, я понимаю ваши требования как:

published = 1
AND
publish_up <= now
AND
(
    publish_down = 0000-00-00 00:00:00
    OR
    publish_down > now
)
  • where()имеет значение клея по умолчанию AND.
  • andWhere()имеет значение клея по умолчанию OR.

Чтобы перевести это в конструктор запросов Joomla, вы должны написать:

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

Требуемая логика идеально согласуется с клеями по умолчанию для методов, поэтому объявления клеев не требуются.

Визуализированный 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')

Заметки:

  1. Связывание или отсутствие цепочки вызовов методов не влияет на способ создания sql. Другими словами, вы не получаете и не теряете скобки от продолжения или разрыва «цепочки» вызовов методов.

  2. Я бы использовал, CURRENT_TIMESTAMPесли только вы $dateне то, что я думаю. Нравиться:

    $db->quoteName('publish_up') . ' <= CURRENT_TIMESTAMP',
    
  3. Вот еще один из моих постов, в котором рассматриваются различные комбинации синтаксиса создания .