2016-12-17 53 views
2

我在模型中有很多關係。我想顯示使用搜索模型篩選和導出網格的網格視圖中接收的訂單,產品,訂單的總數,但我無法弄清楚如何通過排序來計算數量。我有以下關係。如何從網格中的多個關係中獲取計數Yii2搜索模型

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']); 
} 

我需要每一個的計數。任何想法,如何去做?

回答

0

感謝,並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'], 
    ], 
]); ?> 
1

您只需調用這樣的方法:

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

這是如何工作的:

當你真正調用方法返回一個yii\db\ActiveQueryInterface實例,所以你可以使用方法如count()all()one()

通常當你訪問releationship你會做它,如果它是一個屬性,從你模型課程喜歡這個$model->products。通過這種方式,您可以得到yii\db\ActiveQueryInterface實際返回的結果,用all()one()進行評估,具體取決於您是否使用了hasManyhasOne

相關問題