Mysql Создание динамического запроса с использованием having и groupby

Boris

Новичок
Здравствуйте!
У меня есть две таблицы: color_product и material_product
В них есть id_product и id_color, id_material и part_product(часть товара)
У товара может быть несколько цветов и несколько материалов

Пользователь ищет товар, он может выбрать цвет, или несколько цветов.
Может выбрать материал товара или несколько материалов.
Может выбрать и цвет/цвета и материал/материалы вместе.

Делать проверку на каждый случай и составлять нужный select, комбинаций может быть много, так как товар может состоять из трех составляющих (дверь,корпус,столешница) и каждая из них иметь свой цвет, мне кажется не правильно и в конце концов все равно что-то упущу.
Я решил создать нечто универсальное, но боюсь, что что не так.
Прошу Вас посмотрите и поправьте или дайте какой-то совет.

Я проверяю если выбран хоть один цвет и создаю условия:
Код:
$string_from .= ',des_color as color';
$string_where_relationship_tables .= ' and products.id_product = color.id_product ';
$string_where_colors = ' and (
                                    (color.products_part = 1 and color.colors_name IN('.mysqli_real_escape_string($link,$p_color_base).'))
                                    or
                                    (color.products_part = 2 and color.colors_name IN('.mysqli_real_escape_string($link,$p_color_door).'))
                                    ) ';
$string_group_by = 'group by color.id_product';
$string_having = 'having count(*) > 0'
Проверяю если выбран хоть один материал и создаю условие:
Код:
$string_from .= ',des_products_material as material';
$string_where_relationship_tables .= ' and products.id_product = material.id_product ';
$string_where_materials = ' and (
                                    (material.products_part = 1 and material.materials_name IN('.mysqli_real_escape_string($link,$p_material_base).'))
                                    or
                                    (material.products_part = 2 and material.materials_name IN('.mysqli_real_escape_string($link,$p_material_door).'))
                                    or
                                    (material.products_part = 3 and material.materials_name IN('.mysqli_real_escape_string($link,$p_material_cover).'))
                                    ) ';
$string_group_by = 'group by material.id_product';
$string_having = 'having count(*) > 0 ';
чтобы не было пустого условия в IN я делаю flaf равный 0
Код:
$p_material_base='0'.(implode(",",$_GET['material_base']));
$p_material_door='0'.(implode(",",$_GET['material_door']));
$p_material_cover='0'.(implode(",",$_GET['material_cover']));
$p_color_base = '0'.(implode(",",$_GET['color_base']));
$p_color_door = '0'.(implode(",",$_GET['color_door']));
получается что к примеру $p_material_door может иметь значение 012

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

Спасибо Вам всем за время и внимание, буду рад Вашим замечаниям и идеям.
 
Последнее редактирование:

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Boris, он имеет в виду, что данные в запрос должны попадать только через подстановку плейсхолдером.
 

Boris

Новичок
Boris, он имеет в виду, что данные в запрос должны попадать только через подстановку плейсхолдером.
правильно ли я понимаю? плейсхолдер-это шаблон в который добавляются переменные?
Я перед тем как использовать ту или иную переменную в запросе проверяю на валидность.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Boris, отчасти. Плейсхолдеры бывают разные, типизированные, к примеру. Биндинг переменной в запросе на себя берет обертка над драйвером БД.

PHP:
$this->db->select('SELECT * FROM users where id=?i', $id);
Пример типизированного плейсхолдера, когда подразумевается, что на место ?i передается переменная $id и приводится в типу integer.
 

Boris

Новичок
Boris, отчасти. Плейсхолдеры бывают разные, типизированные, к примеру. Биндинг переменной в запросе на себя берет обертка над драйвером БД.

PHP:
$this->db->select('SELECT * FROM users where id=?i', $id);
Пример типизированного плейсхолдера, когда подразумевается, что на место ?i передается переменная $id и приводится в типу integer.
Скажите, я никогда не сталкивался с Плейсхолдерами, где их брать как работать. До сего момента все запросы я составлял именно с помощью проверки данных и с использованием mysqli_real_escape_string создавал string запрос и таким макаром работал.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Надо гуглить и искать по форуму.
 

AnrDaemon

Продвинутый новичок
Тем, что ты выполняешь дурную работу, которую за тебя другие люди сделали десять лет назад.
 

Boris

Новичок
c0dex, Absinthe, AnrDaemon, Спасибо. Другими словами Вы предлагаете использовать класс PDO вместо процедурного стиля. Дело в том что проект уже написан как написан, проблема защиты стоит на первом месте и все данные проверяются так что вопрос инъекции конечно актуальный, но переписывать весь проект, время нет, потихоньку внедряем PDO и со временем скорее всего заменим обращение к БД через PDO. mysql_ было проще заменить на mysqli_ чем переписывать подключения и обращение и отправку запросов под PDO. В конечном счете весь этот класс заменяет писанину и проверки, но может управление саморучно не так уж и плохо!?

Вопрос был больше напрвлен на сам запрос, т.е. его корректность
Код:
Я проверяю если выбран хоть один цвет и создаю условия:
Код:
$string_from .= ',des_color as color';
$string_where_relationship_tables .= ' and products.id_product = color.id_product ';
$string_where_colors = ' and (
                                    (color.products_part = 1 and color.colors_name IN('.mysqli_real_escape_string($link,$p_color_base).'))
                                    or
                                    (color.products_part = 2 and color.colors_name IN('.mysqli_real_escape_string($link,$p_color_door).'))
                                    ) ';
$string_group_by = 'group by color.id_product';
$string_having = 'having count(*) > 0'
Проверяю если выбран хоть один материал и создаю условие:
Код:
$string_from .= ',des_products_material as material';
$string_where_relationship_tables .= ' and products.id_product = material.id_product ';
$string_where_materials = ' and (
                                    (material.products_part = 1 and material.materials_name IN('.mysqli_real_escape_string($link,$p_material_base).'))
                                    or
                                    (material.products_part = 2 and material.materials_name IN('.mysqli_real_escape_string($link,$p_material_door).'))
                                    or
                                    (material.products_part = 3 and material.materials_name IN('.mysqli_real_escape_string($link,$p_material_cover).'))
                                    ) ';
$string_group_by = 'group by material.id_product';
$string_having = 'having count(*) > 0 ';
 

Фанат

oncle terrible
Команда форума
ну и что? будущее это еще когда наступит. к тому же в пхп сотни удаленных расширений - и все прекрасно работают.

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

Фанат

oncle terrible
Команда форума
судя по всему, у тебя в базе есть только один цвет лежит
 

Boris

Новичок
ну и что? будущее это еще когда наступит. к тому же в пхп сотни удаленных расширений - и все прекрасно работают.

в общем, ты сделал бесполезную работу.
почему-то всегда так бывает. сначала человек делает какую-нибудь бессмысленную глупость, и страшно гордится собой.
а потом, когда ему советуют сделать что-то умное - обязательно отказывается. кругом ведь идиоты, а он один умный
ну совсем не так, если Вы читали, то я написал, что потихоньку мы переходим, и потом проект это дело не одного программиста, а еще как минимум владельца. Все советы доброжелательных форумчан учитываются и на них учатся ну или хотябы ставят галочку что такое есть.
 
Сверху