livestreet-framework icon indicating copy to clipboard operation
livestreet-framework copied to clipboard

Есть такое в ORM?

Open kerbylav opened this issue 10 years ago • 6 comments

Возможно уже каким-то образом есть, но вот так на первый взгляд не вижу: хотелось бы группировок условий AND и OR в условии #where для ORM

Сейчас такая конструкция:

        $aFilter['#where'] = array(
                'creator_id=?' => array(10),
                'status=?' => array(2),
        );

результирует в условие creator_id=10 AND status=2, предлагаю добавить конструкцию

        $aFilter['#where'] = array(
            array(
                'creator_id=?' => array(10),
                'status=?' => array(2),
            ),
            array(
                'status=?' => array(1),
            )
        );

которая бы результировала в условие (creator_id=10 AND status=2) OR (status=1)

И дальше рекурсивно по иерархии:

            array(
                'creator_id=?' => array(10),
                'status=?' => array(2),
                array(
                    array(
                        'price>?' => array(100)
                    ),
                    array(
                        'price=?' > array(0)
                    )
                )
            ),
            array(
                'status=?' => array(1),
            )

условие (creator_id=10 AND status=2 AND ((price>100) OR (price=0))) OR (status=1)

Это все позволит формировать комплексные динамические запросы используя все тот же движок ORM со всеми его остальными вкусностями.

Да, и еще добавить какой-нибудь #-ключ для задания дополнительные тегов кэша.

kerbylav avatar Sep 27 '14 09:09 kerbylav

На самом деле его можно вот так использовать:

$aFilter['#where']=array('(creator_id=? AND status=? AND ((price>?) OR (price=?))) OR status=?' => array(10,2,100,0,1));

mzhelskiy avatar Sep 27 '14 11:09 mzhelskiy

Нет-нет, идея в том, что бы можно было формировать фильтр последовательно и динамично по критериям, что-то подобное функционалу buildFilter в мэппере топиков, только для ORM и с гарантированным нормальным экранированием.

kerbylav avatar Sep 27 '14 16:09 kerbylav

Можно не писать так:

        $aFilter['#where'] = array(
                'creator_id=?' => array(10),
                'status=?' => array(2),
        );

а так:

        $aFilter['#where'] = array(
                'creator_id' => 10,
                'status' => 2,
        );

в этом плане орм лс гибок.

Это все позволит формировать комплексные динамические запросы используя все тот же движок ORM со всеми его остальными вкусностями.

но не совсем интуитивно понятно что это будет "ИЛИ"

Да, и еще добавить какой-нибудь #-ключ для задания дополнительные тегов кэша.

не совсем понял, есть же #cache

и с гарантированным нормальным экранированием.

то, что показал Максим - гарантировано экранируется.

psnet avatar Dec 08 '14 11:12 psnet

а так:

я специально максимально параметризированную одинаковую запись использовал

но не совсем интуитивно понятно что это будет "ИЛИ"

Я не знаю, как еще сделать это более интуитивно понятно, но на мой взгляд и так все хорошо - если ключ у элемента массива не числовой - значит условие И, если числовой - ИЛИ

не совсем понял, есть же #cache

Если использовать #cache то надо и стандартные теги на сохранение и удаление в нем задавать, а это дополнительный лишний код для их формирования. А вот именно дополнительные ключи было бы лучше

то, что показал Максим - гарантировано экранируется.

Это понятно. Идея же в стандартном механизме динамического формирования, чтобы каждый использовал его, а не изгалялся как хочет.

kerbylav avatar Dec 08 '14 12:12 kerbylav

Я не знаю, как еще сделать это более интуитивно понятно

Единственное, что мне приходит в голову это сделать такую запись, что:

Если ключ элемента массива числовой - это "скобки" и тогда первым элементом массива можно указать, что условие OR, если первый элемент не OR, то считать, что перед скобками условие AND. Если не числовой то это тоже самое, что и сейчас, т.е. как-то так.

        $aFilter = array(
            '#where' => array(
                array(
                    'creator_id=?' => array(10),
                    'status=?' => array(2),
                    array(
                        array(
                            'price>?' => array(100)
                        ),
                        array(
                            'OR',
                            'price=?' > array(0)
                        )
                    ),
                ),
                array(
                    'OR',
                    'status=?' => array(1),
                )
            )
        );

преобразуется в запись

AND (creator_id=10 AND status=2 AND ((price>100) OR (price=0))) OR (status=1)

В предыдущем варианте синтаксиса было плохо с объединением условий AND в группы, т.е. задать такое условие было проблематично:

((status=0 and sum>100) and (status=2 and sum<=100)) or (status=1)

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

kerbylav avatar Dec 09 '14 03:12 kerbylav

Подумал, что вот такая реализация будет чище и интуитивно понятней:

        $aFilter = array(
            '#where' => array(
                array(
                    'creator_id=?' => array(10),
                    'status=?' => array(2),
                    array(
                            'price>?' => array(100),
                            '#or price=?' > array(0),
                        )
                    ),
                ),
                array(
                    '#or status=?' => array(1),
                )
            )
        );

Получается:

AND (creator_id=10 AND status=2 AND (price>100 OR price=0)) OR (status=1)

Т.е. array внутри это скобки, если ключ-условие начинается с #or - надо объединять с OR, и если это первый ключ в массиве-скобках, то и перед скобками ставится OR.

kerbylav avatar Apr 01 '15 19:04 kerbylav