【问题标题】:Sorting calculated fields in Yii2 (Grid View)Yii2中的计算字段排序(网格视图)
【发布时间】:2016-01-30 13:46:15
【问题描述】:

我需要在 GridView 中对一些字段(asc、desc)进行排序,但会计算相同的字段。看下面的代码: 搜索模型:

class ObjectSearch extends Object {
use SearchModelTrait;

public function rules()
{
    return [
        ['id', 'integer', 'min' => 1],
    ];
}

public function search($params)
{
    $this->company_id = \Yii::$app->user->identity->companyId;
    $query = Object::find()->where(['company_id' => $this->company_id]);
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
        'pagination' => false,
    ]);
    $dataProvider->setSort([
        'attributes' => [
            'id',
            'name',
            'lastReportResult' => [
                'asc' => ['lastReportResult' =>SORT_ASC ],
                'desc' => ['lastReportResult' => SORT_DESC],
                'default' => SORT_ASC
            ],
            'reportPercentDiff'
        ]
    ]);

    if (!($this->load($params,'ObjectSearch') && $this->validate())) {
        return $dataProvider;
    }

    $this->addCondition($query, 'id');

    return $dataProvider;
}

对象模型中的方法:

public function getLastReportResult()
{
    $lastReport = $this->getLastReport();
    $message = 0;

    if (!empty($lastReport)) {
        $statistic = new ReportStatistic($lastReport);
        $message = $statistic->getPercent();
    }

    return $message;
}

/**
 * @return int
 */
public function getReportPercentDiff()
{
    $lastReport = $this->getLastReport();
    $message = 0;

    if (!empty($lastReport)) {
        $statistic = $lastReport->getReportDiff();

        if (!empty($statistic['diff'])) {
            $message = $statistic['diff']['right_answers_percent_diff'];
        } elseif (!empty($statistic['message'])) {
            $message = $statistic['message'];
        }
    }
    return $message;
}

所以,通过这种方法,我正在计算需要排序的两个字段的值。这种方式不起作用,我有一个数据库异常,因为对象表没有这个字段。 exception 如何对这些字段进行排序?

【问题讨论】:

  • 你好。你找到答案了吗?

标签: php sorting gridview yii2 yii2-model


【解决方案1】:

更新:我是这个答案的作者,这个答案不准确。首选方式是使用database view

将两个公共属性添加到ObjectSearch.php 并将其标记为安全

class ObjectSearch extends Object {
    use SearchModelTrait;
    public $lastReportResult, $reportPercentDiff;
    public function rules()
    {
        return [
            ['id', 'integer', 'min' => 1],
            [['lastReportResult', 'reportPercentDiff'], 'safe']
        ];
    }

    public function search($params)
    {
        $this->company_id = \Yii::$app->user->identity->companyId;
        $query = Object::find()->where(['company_id' => $this->company_id]);
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'pagination' => false,
        ]);
        $dataProvider->setSort([
            'attributes' => [
                'id',
                'name',
                'lastReportResult' => [
                    'asc' => ['lastReportResult' =>SORT_ASC ],
                    'desc' => ['lastReportResult' => SORT_DESC],
                    'default' => SORT_ASC
                ],
                'reportPercentDiff' => [
                    'asc' => ['reportPercentDiff' =>SORT_ASC ],
                    'desc' => ['reportPercentDiff' => SORT_DESC],
                    'default' => SORT_ASC
                ],                
            ]
        ]);

        if (!($this->load($params,'ObjectSearch') && $this->validate())) {
            return $dataProvider;
        }

        $this->addCondition($query, 'id');

        return $dataProvider;
}

然后在index.php(您在其中有网格视图的查看文件)中添加lastReportResultreportPercentDiff 到所有属性的数组中(所有属性列表ob Object 模型)

...
<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'filterModel' => $searchModel,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],

        
        // your other attribute here
        'lastReportResult',
        'reportPercentDiff',

        ['class' => 'yii\grid\ActionColumn'],
    ],
]); ?>
...

欲了解更多信息,您可以访问Kartik's blog at Yii

【讨论】:

  • 如果您在数据库表中没有列 lastReportResultreportPercentDiff,这个答案显然是行不通的。
  • 那么在这种情况下,如果您没有这些列,那么您可以通过以下方式在网格视图中定义一个属性。 RelatioName.columnName。例如,如果具有列 userId 的 post 表与具有 PK 列 id 和其他名为 name 的列的用户相关,并且如果您在 post 模型中与 getUser 有关系,那么在网格视图中将 user.name 作为属性将工作正常。
  • 我的意思是当你根本没有这个列的情况下,在数据库中没有任何地方,它是100%在Yii2模型内的PHP端计算的,基于另一个来自数据库的数据。您可以按此类列设置过滤,并且可以很好地在网格中显示它,但是按它进行排序是一个可怕的痛苦,并且正在以完全不同的方式完成。
  • 是的,但你可以做到。 yiiframework.com/wiki/621/…
  • 考虑到这里几年后这样做,我可以证明这不起作用,Kartik 提出的这个解决方案也不适用于完全计算的字段。接受的答案应该被否定,这应该被标记为未解决。
【解决方案2】:

虽然这是一个旧线程,但偶然发现了这个并试图找到其他方法来实现对纯计算字段的排序无济于事......不幸的是,这篇文章也不是答案......只是我觉得需要在此处发布它以提醒那些仍在寻找解决方案的人,以免在尝试给出的解决方案但仍然失败时挠头。

据我测试,文档或参考链接中的给定示例仅适用于数据库架构中有列(无论是在主表还是相关表中)。如果您创建的虚拟属性/计算字段基于计算(例如表上 2 列的乘法),它将不起作用

例如: 表购买:|购买ID |产品编号 |数量 | 餐桌产品:|产品编号 |单价 |

然后,如果我们为模型“purchase”使用虚拟属性“purchase_total”,它是数量和 unit_price 的乘积(来自 product_id 上的购买和产品的连接表),最终你会遇到一个错误,说“purchase_total”当您尝试使用目前讨论的方法对它们进行排序时,找不到列。

【讨论】:

  • 计算字段对于快速开发来说是一件好事,但我认为,如果它可以由您的数据库计算 - 您应该使用数据库。
  • 对此的论据:薄模型层和浮动 0,3 问题。尝试计算db中的动态字段并使用十进制类型的价格(或使用定点算术方法)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多