yii分页问题试图使用2个标准

时间:2016-10-18 20:25:03

标签: mysql yii pagination

免责声明我是自学成才。获得了我对php阅读论坛的基本知识。我是一个新手,并且对yii几乎一无所知。

我有一个控制器,可以在我们的网上商店中显示产品。我想在最后几页显示缺货产品。

我知道我可以按库存数量排序,但希望每次重新加载页面时库存产品都会更改订单。

我的解决方案(可能错误但有点有效)是运行两个查询。一个有库存的产品,随机分类。一个缺货产品也随机订购。然后我合并两个结果数组。使用下面的代码可以解决这个问题(虽然我觉得必须有一个比运行两个查询更有效的方法)。

问题在于这会扰乱分页。返回的每个产品都列在同一页面上,更改页面显示相同的结果。据我所知,分页一次仅适用于1个CDbCriteria。我已经看过yii docs for 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可以用于分页(因为它将包括与前两个产品的组合结果相同数量的产品)。所以我尝试添加它(criteria1和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
            ));  

我确信我错过了一些非常明显的东西......一整天都在寻找无处可寻。

1 个答案:

答案 0 :(得分: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

这样订单是完全可预测的(即使用户可能甚至不知道存在由唯一ID应用的排序)。