【问题标题】:How to get count from many relations in a Grid Yii2 Search Model如何从 Grid Yii2 搜索模型中的许多关系中获取计数
【发布时间】:2016-12-17 12:12:02
【问题描述】:

我在模型中有很多关系。我想使用过滤器和导出网格的搜索模型在网格视图中显示订单、产品、订单的总数,但我无法弄清楚如何通过排序获得计数。我有以下关系。

public function getProducts()
{
    return $this->hasMany(Product::className(), ['user_id' => 'user_id']);
}
public function getShopImages(){
    return $this->hasMany(ShopImage::className(), ['user_id' => 'user_id']);
}
/**
 * @return \yii\db\ActiveQuery
 */
public function getOrders()
{
    // Customer has_many Order via Order.customer_id -> id
    return $this->hasMany(Order::className(), ['user_id' => 'user_id']);
}

/**
 * @return \yii\db\ActiveQuery
 */
public function getOrderrs()
{
    // Customer has_many Order via Order.customer_id -> id
    return $this->hasMany(Order::className(), ['merchant_id' => 'user_id']);
}

我需要对每一个进行计数。有什么想法,怎么做?

【问题讨论】:

    标签: php gridview yii2


    【解决方案1】:

    你可以像这样调用方法:

    $model->getProducts()->count();
    

    这是如何工作的:

    当你调用实际方法时返回一个yii\db\ActiveQueryInterface实例,所以你可以使用count()all()one()等方法。

    通常当您访问关系时,您会像 $model->products 这样的模型类的属性一样进行操作。通过这种方式,您可以获得该方法实际返回的 yii\db\ActiveQueryInterface 的结果,使用 all()one() 进行评估,具体取决于您使用的是 hasMany 还是 hasOne

    【讨论】:

      【解决方案2】:

      请查看以下链接。对你有帮助。

      一个。 https://github.com/yiisoft/yii2/issues/2179

      b. http://www.yiiframework.com/forum/index.php/topic/62772-how-to-get-count-in-relation-table-in-yii2-activerecord/

      public function getProducts(){
       return $this->hasMany(Product::className(), ['user_id' => 'user_id'])->count();}
      

      【讨论】:

        【解决方案3】:

        谢谢,this link from github也帮了我很多。

            +
             +## Selecting extra fields
             +
             +When Active Record instance is populated from query results, its attributes are filled up by corresponding column
             +values from received data set.
             +
             +You are able to fetch additional columns or values from query and store it inside the Active Record.
             +For example, assume we have a table named 'room', which contains information about rooms available in the hotel.
             +Each room stores information about its geometrical size using fields 'length', 'width', 'height'.
             +Imagine we need to retrieve list of all available rooms with their volume in descendant order.
             +So you can not calculate volume using PHP, because we need to sort the records by its value, but you also want 'volume'
             +to be displayed in the list.
             +To achieve the goal, you need to declare an extra field in your 'Room' Active Record class, which will store 'volume' value:
             +
             +```php
             +class Room extends \yii\db\ActiveRecord
             +{
             +    public $volume;
             +
             +    // ...
             +}
             +```
             +
             +Then you need to compose a query, which calculates volume of the room and performs the sort:
             +
             +```php
             +$rooms = Room::find()
             +    ->select([
             +        '{{room}}.*', // select all columns
             +        '([[length]] * [[width]].* [[height]]) AS volume', // calculate a volume
             +    ])
             +    ->orderBy('volume DESC') // apply sort
             +    ->all();
             +
             +foreach ($rooms as $room) {
             +    echo $room->volume; // contains value calculated by SQL
             +}
             +```
             +
             +Ability to select extra fields can be exceptionally useful for aggregation queries.
             +Assume you need to display a list of customers with the count of orders they have made.
             +First of all, you need to declare a `Customer` class with 'orders' relation and extra field for count storage:
             +
             +```php
             +class Customer extends \yii\db\ActiveRecord
             +{
             +    public $ordersCount;
             +
             +    // ...
             +
             +    public function getOrders()
             +    {
             +        return $this->hasMany(Order::className(), ['customer_id' => 'id']);
                      //->from(['your_table_alias'=>Order::className()])
             +    }
             +}
             +```
             +
             +Then you can compose a query, which joins the orders and calculates their count:
             +
             +```php
             +$customers = Customer::find()
             +    ->select([
             +        '{{customer}}.*', // select all customer fields
             +        'COUNT({{order}}.id) AS ordersCount' // calculate orders count
             +    ])
             +    ->joinWith('orders') // ensure table junction
             +    ->groupBy('{{customer}}.id') // group the result to ensure aggregation function works
             +    ->all();
        

        在你的搜索模型中,你应该这样做

        class Search extends yourModel
        {
            /**
             * @inheritdoc
             */
            public function rules()
            {
                return [
                    your rules.......
                ];
            }
        
            /**
             * @inheritdoc
             */
            public function scenarios()
            {
                // bypass scenarios() implementation in the parent class
                return Model::scenarios();
            }
        
            /**
             * Creates data provider instance with search query applied
             *
             * @param array $params
             *
             * @return ActiveDataProvider
             */
            public function search($params)
            {
                $query = Fromto::find()->joinWith('orders')->groupBy('{{customer}}.Id');
        
                $dataProvider = new ActiveDataProvider([
                    'query' => $query,
                ]);
        
                $this->load($params);
        
                if (!$this->validate()) {
                    // uncomment the following line if you do not want to return any records when validation fails
                    // $query->where('0=1');
                    return $dataProvider;
                }
        
                $query->andFilterWhere([
                    'Id' => $this->Id,
                    '{{customer}}.customer_column' => $this->your_column,
                ]);
        
                return $dataProvider;
            }
        }
        

        在视图中

        <?= GridView::widget([
            'dataProvider' => $dataProvider,
            'filterModel' => $searchModel,
            'columns' => [
                ['class' => 'yii\grid\SerialColumn'],
        
                'Id',
                [
                    'attribute'=>'your_column',
                    'label'=>'your label',
                    'value'=>function($model){
                        return $model->orders->order_column;
                    }
                ],
                .....
        
                ['class' => 'yii\grid\ActionColumn'],
            ],
        ]); ?>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多