Тема: Дополнительный фильтр по наличию фотографий товара

Добрый день. Хотел спрятать в каталоге товары без фото. В классе \Catalog\Model\Api метод filterRequest изменил следующим образом, чтобы в выборку попали только товары, для которых есть соответствие в таблице с фотографиями:

function filterRequest()
    {
        $config = \RS\Config\Loader::byModule($this);

        \RS\Orm\Request::make()
                ->join($this->obj_instance, 'P.id = A.entity_id', 'P')
                ->where('public = 1');
        if ($config['hide_unobtainable_goods'] == 'Y') {
            $q->where('num > 0');
        }
        $adv_config = \RS\Config\Loader::byModule("custom");

        if ($adv_config['hide_nophoto_product'] == 1) {
            $q->join(new \Photo\Model\Orm\Image, 'I.linkid = A.entity_id', 'I');
        }
        return $q;
    }

Соответственно в конфиге модуля custom данная настройка есть и установлена в 1.

Re: Дополнительный фильтр по наличию фотографий товара

И в чём вопрос?)

3

Re: Дополнительный фильтр по наличию фотографий товара

Не работает ))

4 Отредактировано Закусило Александр (28.09.2016 20:22:51)

Re: Дополнительный фильтр по наличию фотографий товара

Ну прибавили Вы таблицу с фото. А где WHERE с условием?

5

Re: Дополнительный фильтр по наличию фотографий товара

А разве сам по себе join не подразумевает, что в выборку попадает только пересечение? Таким образом моя логика говорит мне, что останутся в выборке только товары, у которых есть соответствие в таблице с изображениями. Разве не так?

Re: Дополнительный фильтр по наличию фотографий товара

Ах да там же у Вас innerjoin. В проверьте у Вас в эту ветку заходит.
Можно вывести итоговый SQL так:

var_dump($q->toSql());

7

Re: Дополнительный фильтр по наличию фотографий товара

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

8 Отредактировано Закусило Александр (30.09.2016 14:06:18)

Re: Дополнительный фильтр по наличию фотографий товара

filterSection по идее срабатывает тогда когда вы пытаетесь фильтровать что-то. Вам нужен вывод сразу во всём каталоге только тех что с фото? Я правильно понимаю?

Если да, то тогда лучше всего подвеситься из своего модуля на хук страницы со списком товаров. И уже у объекта API добавить нужный фильтр.
controller.beforeexec.catalog-front-listproducts

Там первым аргументом будет.

/**
* @param \Catalog\Controller\Front\ListProducts $controller - объект контроллера
* @param string $action - наименование метода, который отработал (использовать для нужного)
*/
public static function controllerBeforeexecCatalogFrontListproducts($controller, $action)
{
     $q = $controller->api->queryObj(); //Потому что у фронт контроллера публичное свойство $api, в котором объект API товаров
     //И нужные мне действия с \RS\Orm\Request в $q, т.е. обычным запросом
}

Попробуйте, если это оно.

9

Re: Дополнительный фильтр по наличию фотографий товара

Ух ты, похоже, что да, оно. Да и из своего модуля все-таки кошернее. Отпишусь по-результату. Спасибо.

10 Отредактировано Максим (30.09.2016 17:14:22)

Re: Дополнительный фильтр по наличию фотографий товара

Александр, спасибо. Заработало. Вот текст запроса. Новая проблема - после JOIN в поле id товара передается теперь id изображения. Соответственно, в каталоге начинается вакханалия, ибо везде в переменной $product.id теперь id картинки. Как-то можно исключить из секции SELECT поле Img.id?

SELECT * FROM `readyscriptyoung`.`rs_product` as A 
INNER JOIN `readyscriptyoung`.`rs_product_x_dir` as X ON A.id = X.product_id 
INNER JOIN `readyscriptyoung`.`rs_images` as Img ON A.id = Img.linkid 
WHERE (`A`.`site_id` = '1') AND `X`.`dir_id` IN ('675','676','677','678','679','680','681','682','683','684','685','686','687','688','689','690','691','692','834','835','837','845','846','847','848','849','850','851','852','853','854','855','907','674','694','695','696','698','699','700','701','702','703','838','856','857','858','875','876','900','901','902','904','905','906','693','673','672') AND `A`.`public` = '1' AND `A`.`num` > '0' 
ORDER BY dateof DESC

Re: Дополнительный фильтр по наличию фотографий товара

Как и во всех SQL запросах, нужно указать то что собираетесь выбирать конкретно.

SELECT A.*
->select('A.*')

12

Re: Дополнительный фильтр по наличию фотографий товара

Не, так не пойдет. Тогда приджойненные цены не выведутся. Но я нашел способ. Вместо join использовал where с подзапросом и условием, что id товара находится в результатах этого запроса.

$this->queryObj()
                ->where("A.id IN (SELECT `linkid` FROM `readyscriptyoung`.`rs_images`)");

13

Re: Дополнительный фильтр по наличию фотографий товара

только вот мне не нравится, что замес получился с sql синтаксисом. Хочется как-то в отдельный запрос вывести то, что в скобках, но не пойму, как.

14

Re: Дополнительный фильтр по наличию фотографий товара

Все, теперь я доволен.

$adv_config = \RS\Config\Loader::byModule("custom");
        if ($adv_config['hide_nophoto_product'] == 1) {
            $qImage = new \RS\Orm\Request();
            $qImage
                ->select('linkid')
                ->from(new \Photo\Model\Orm\Image(), 'Img');
            $this->queryObj()
                ->where("A.id IN (".$qImage->toSql().")");

        }

15 Отредактировано Закусило Александр (30.09.2016 20:18:21)

Re: Дополнительный фильтр по наличию фотографий товара

ВЫ можете через запятую указать те таблицы которые нужны в SELECT.

A.*, B.* и т.д.

Т.е. исключите картинки.

16

Re: Дополнительный фильтр по наличию фотографий товара

Финальный вариант, если кого вдруг заинтересует:

$adv_config = \RS\Config\Loader::byModule("custom"); /*Проверяем настройку показа товаров без фотографий*/
        if ($adv_config['hide_nophoto_product'] == 1) {

            $q = $this->queryObj();

            if ($q->select === '*') {
                $q->select = null;
                $q->select('A.*, X.*');
            }

            $q->join(new \Photo\Model\Orm\Image, 'I.linkid = A.id', 'I');
            $q->groupby('A.id');

        }

Выяснилось, что при использовании подзапроса в секции WHERE - ломается напрочь поиск и крайне медленно выполняется запрос в случае использования фильтров на странице каталога. Сделал в итоге через JOIN и добавил условие, так как при поиске должны выбираться только поля из таблицы `A`, а таблица `X` - вообще не джойнится при поиске. Косяков не обнаружено и скорость отличная.