2016-10-18 3 views
0

Отказ от ответственности Я самоучкой. Получил мое рудиментарное знание форумов для чтения php. Я sql newb, и почти ничего не знаю о yii.yii pagination issue пытается использовать 2 критерия

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

Я знаю, что я мог бы сортировать по количеству запаса, но хотел бы, чтобы товары на складе меняли порядок каждый раз, когда страница перезагружается.

Мое решение (возможно, неправильное, но любопытное) - это запустить два запроса. Один для продукта с запасом, отсортированный случайным образом. Одновременно с заказом случайно выставляется товар. Затем я объединяю два результирующих массива. Это много работает с использованием кода ниже (хотя я чувствую, что должен быть более эффективный способ, чем запуск двух запросов).

Проблема в том, что это испортит разбивку на страницы. Каждый возвращенный продукт указан на одной странице, и смена страниц показывает те же результаты. Насколько я могу сказать, разбиение на страницы работает только для 1 CDbCriteria за раз. Я просмотрел документы yii для CPagination для этого, но никуда не денусь.

 $criteria=new CDbCriteria; 
     $criteria->alias = 'Product'; 
     $criteria->addCondition('(inventory_avail>0 OR inventoried=0)'); 
     $criteria->addCondition('Product.parent IS NULL'); 
     $criteria->addCondition('web=1'); 
     $criteria->addCondition('current=1'); 
     $criteria->addCondition('sell>sell_web'); 
     $criteria->order = 'RAND()'; 

     $criteria2=new CDbCriteria; 
     $criteria2->alias = 'Product'; 
     $criteria2->addCondition('(inventory_avail<1 AND inventoried=1)'); 
     $criteria2->addCondition('Product.parent IS NULL'); 
     $criteria2->addCondition('web=1'); 
     $criteria2->addCondition('current=1'); 
     $criteria2->addCondition('sell>sell_web'); 
     $criteria2->order = 'RAND()'; 

     $crit1=Product::model()->findAll($criteria); 
     $crit2=Product::model()->findAll($criteria2); 
     $models=array_merge($crit1,$crit2);     

     //I know there is something wrong here, no idea how to fix it.. 
     $count=Product::model()->count($criteria); 
     $pages=new CPagination($count); 
     //results per page 
     $pages->pageSize=30; 
     $pages->applyLimit($criteria); 

     $this->render('index', array(
     'models' => $models, 
      'pages' => $pages 
      )); 

Ясно, что я нахожусь над головой. Любая помощь приветствуется.

Редактировать:

Я полагал, что треть CDbCriteria, что включает в себя как в наличии и из деталей штока может быть использована для разбиения на страницы (как это будет включать в себя одинаковое количество продуктов, как объединенные результаты первого 2). Так что я попытался добавить этот (факторам1 и criteria2 остается тем же):

 $criteria3=new CDbCriteria; 
     $criteria3->alias = 'Product'; 
     //$criteria3->addCondition('(inventory_avail>0 OR inventoried=0)'); 
     $criteria3->addCondition('Product.parent IS NULL'); 
     $criteria3->addCondition('web=1'); 
     $criteria3->addCondition('current=1'); 
     $criteria3->addCondition('sell>sell_web'); 
     //$criteria3->order = 'RAND()'; 

     $crit1=Product::model()->findAll($criteria); 
     $crit2=Product::model()->findAll($criteria2); 
     $models=array_merge($crit1,$crit2);     

     $count=Product::model()->count($criteria3); 
     $pages=new CPagination($count); 
     //results per page 
     $pages->pageSize=30; 
     $pages->applyLimit($criteria3); 

     $crit1=Product::model()->findAll($criteria); 
     $crit2=Product::model()->findAll($criteria2); 
     $models=array_merge($crit1,$crit2); 

     $this->render('index', array(
     'models' => $models, 
      'pages' => $pages 
      )); 

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

+0

Использование разбиения на страницы со случайным порядком обычно не имеет смысла, зачем вы это делаете? Почему не просто один запрос с несколькими условиями заказа (сначала по доступности, то по какому бы ни было ваше основное поле сортировки)? –

+0

Спасибо за ответ Майк. При нажатии на категорию в нашем магазине иногда может появиться несколько сотен продуктов, мы не хотим, чтобы все эти результаты показывались на одной странице. Случайное упорядочение - это то, что кто-то, возвращающийся в эту категорию, может видеть свежие продукты вместо тех же 30, которые появляются на первой странице. Я не уверен, как упорядочить по доступности, заказывая «inventory_avail», сортируя их по порядку по количеству, чтобы продукты с большим количеством акций всегда показывали сначала, что не идеально для нас. –

ответ

0

Таким образом, вы сталкиваетесь с тем, что является IMO одним из потенциальных недостатков структурных построителей запросов на языке естественных языков. Они могут подумать о том, как вы можете обратиться к проблеме SQL, которая идет по плохому пути при попытке работать с методами «из коробки» для построения запросов. Иногда вам, возможно, придется подумать об использовании необработанных SQL-запросов, которые наиболее подходят для каждой инфраструктуры, чтобы наилучшим образом решить вашу проблему.

Итак, давайте начнем с базового SQL, так как я предлагаю вам подойти к вашей проблеме. Вы можете либо использовать это в своем стиле построителя запросов (если это возможно), либо выполнить необработанный запрос.

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

SELECT 
    field1, 
    field2, 
    /* other fields */ 
    IF(inventory_avail > 0, 1, 0) AS in_inventory 
FROM product 
WHERE /* where conditions */ 
ORDER BY 
    in_inventory DESC, /* sort items in inventory first */ 
    other_field_to_sort ASC /* other sort criteria */ 
LIMIT ?, ? /* pagination row limit and offset */ 

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

Я использую RAND() для целей разбивки на страницы, так как это приведет к тому, что продукты будут отображаться на одной странице за другой, поскольку пользователь разбивает страницы на страницы, а другие продукты, возможно, вообще не отображаются. Либо это, либо вам нужно добавить некоторую дополнительную сложность в вашу заявку, чтобы как-то отслеживать «рандомизированную» версию всего набора результатов для каждого конкретного пользователя. По этой причине, действительно необычно видеть рандомизацию заказа для отображения с разбивкой по страницам.

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

В вашем предложении ORDER BY всегда должно быть достаточно условий сортировки, где конечное (наиболее конкретное) условие гарантирует вам прогнозируемый результат заказа. Зачастую это означает, что вам нужно включить поле автоинкрементного первичного ключа или подобное поле, которое обеспечивает уникальность для строки.

Так скажем, например, у меня была возможность для пользователя сортировать товары по цене, но вы все же, очевидно, хотели сначала показать все инвентаризированные предметы. Теперь предположим, что у вас есть 100K продукты, такие, что у вас будет много «страниц» продуктов с общей ценой при заказе по цене

Если вы использовали это для заказа:

ORDER BY in_inventory DESC, price ASC 

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

Вы, вероятно, хотите сделать что-то вроде:

ORDER BY in_inventory DESC, price ASC, unique_id ASC 

что порядок полностью предсказуем (хотя пользователь может даже не знает, что сортировка применяется по уникальному идентификатору).