Получаю коллекцию по хэшу 'set/bestsellers' (список динамический, стандартный Хиты продаж). Смотрю количество и состав - все верно: 8 товаров, такие-то id. Далее говорю
$collection->addWhere('p.id in('.$pids.')');
где $pids - порядка 50 id существующих товаров (можно и перечень id всех товаров), в числе которых и 8 id присутствующих в списке(коллекции) товаров. Исполнив далее
$collection->getProducts('id', 0, $collection->count())
получаем на выходе 8 товаров с абсолютно иными id. А ожидалось, в данном пусть и слегка утрированном примере, получить все те же 8 id которые и были изначально в списке и коллекции.
10 комментариев
Динамические списки реализованы через ORDER BY и LIMIT.
Когда в условиях появляется WHERE он лишь ограничивает выборку перед сортировкой.
Вероятно тот список из 50 таки не содержит изначальные 8 ID.
Проверил у себя и работает как и ожидалось.
Создаем два стандартных динамических списка "Хиты продаж".
В первом ограничение 8 - best8, во втором 50 - best50.
По ним делаем коллекции:
Посмотрим исходный список:
Получаем id из второго списка, перемешиваем для чистоты эксперимента и добавляем условие в коллекцию:
Смотрим что на выходе:
Получили те же 8 id.
Михаил, отдельное спасибо за то, что не поленился и проверил :)
Полез смотреть... И, о чудо, действительно все сработало. Немного копаний, и ошибка найдена. Список действительно не стандартный bestsellers. Видимо, менял условия и подзабыл. Список формируется по правилу "С высокой оценкой". При этом, т.к. все дело на тестовой установке, никаких оценок у товаров нет. Если вкратце, то вот код
и результат
Аналогичная картина по условиям С низкой оценкой, С зачеркнутой ценой, Самые дешевые.
После уточнения тоже "не принято"? Тогда в чем мое заблуждение? А то некрасивых костылей понавтыкать пришлось...
Давайте тогда пока обсудим...
Для экземпляра класса shopProductsCollection, созданного с хешем списка товаров вы вызываете метод addWhere(). В чём суть этого метода? Если переводить буквально, то "добавить условие WHERE" (с ключевым словом "AND"). Вот вы его и добавляете. Буквально — в SQL-запрос. А раз вы добавили дополнительное условие WHERE, то логично ожидать, что выбранный набор товаров может оказаться другим. Он и получается другим.
Вы же не программист-новичок, который мог бы подумать, что, добавив "where", он получит постфильтрацию для уже выбранного зафиксированного набора товаров. Раз вы знаете, что такое WHERE в SQL, и явно добавляете условие WHERE, странно, что вы ожидаете не того, что сами же и делаете.
Может быть, вам больше пригодится что-то вроде функции array_intersect_key()? Сначала получите список товаров из нужного списка и с помощью этой функции отфильтруйте те, которые не входят в ваш массив $pids.
Или это у меня где-то заблуждение?.. Может, я не до конца понял вашу идею.
Вероятно дело в том, как MySQL выдает результаты при одинаковых значениях полей сортировки.
Простой тест демонстрирует, что не так как ожидает Павел.
Сначала берем два значения без условия:
Получаем:
Теперь добавим условие:
И получаем:
Ну как бы логично, что я хочу получить другой но не набор, а состав товаров из исходного набора :) И запрос получается вполне корректным, т.е. идентичный исходному, но с дополнительными условиями. А дело-то, похоже, действительно в MySQL, как и говорит Михаил (Проектов)...
Нет, Михаил (Ушенин), вы все верно поняли. Это я погорячился на счет костылей. Все решается даже с этой заминкой от MySQL.
Спасибо обоим Михаилам.
Добрый день, (не знаю как писать в личку) можешь помочь лэндинг на сайт запилить?
Мрак какой-то.... )) Нет, ребята, что-то тут не так... Дабы не быть многословным, просто приведу код
и результат
WTF??? ))
В церкви смрад и полумрак,
Дьяки курят ладан. Нет!
И в церкви все не так,
Все не так, как надо.
Путем несложных манипуляций достаем фактически отправляемые SQL запросы для обоих вариантов вызова метода getProducts(). Например, при настройках списка брать 8 товаров с самым низким рейтингом получаем
А теперь Павел, если попробуете выполнить это в консоли MySQL, то опять убедитесь, что причина на стороне базы.
По-прежнему неоднозначность результата вызвана одинаковыми значениями полей сортировки и неоднозначным поведением MySQL в таких ситуациях.
Для получения "стабильных" результатов при одинаковых значениях полей сортировки, необходимо последним в ORDER BY добавить гарантированно уникальный ключ, например id.
Изменение идеологическое и насколько оно необходимо в базовом коде приложения shop не готов спорить.
В плагине можно пользоваться наследником класса shopProductsCollection с измененным методом getOrderBy()
Михаил, как мне кажется, в этом случае это уже не столь важно. Я особо и не настаиваю теперь на том что это ошибка WA. Но, опять же, как мне кажется, до первых более или менее крупных разборок. Вот сложатся несколько факторов:
И если их будет 10-15 - ну чертыхнется и забудет. А если пара тысяч - тут уже другой коленкор... А казалось бы - все по инструкции, все штатно. В общем это такой рояль в кустах, который внезапно может целый концерт закатить.
Ну и так уж, для разрядки: я уже доделал плагин который вполне мог пройтись по описанному выше сценарию. Но т.к. я имел счастье потоптаться на этом грабильном поле пару дней, то, ессно, выжег напалмом там где это было возможно все упоминания id. Но и осталось их достаточно... А кто даст гарантии что все такие чудеса вскрыты? Ну провел я пару сотен экспериментов, больше ничего в глаза не бросилось, вроде бы все в норме, без сюрпризов. А вдруг не все варианты учел? Что тогда? Пользователю же далеко по барабану с бубном какой модели тут пляски происходят, ему нужен ожидаемый результат. А как получить ожидаемый результат? А просто: надо не самокаты самокатить, а использовать предназначенные для этого велосипеды, в т.ч. getProduct('id').
Все имхо, но, имхо, стоит задуматься.