2015-10-03 3 views
3

В моем проекте Yii мне нужно выполнить поиск и сортировку данных по какой-то пользовательской величине. У меня есть таблица 'users', и мне нужно, чтобы каждый экземпляр пользователя имел свойство month_profit, которое должно объединять SQL-данные + множество моих собственных вычислений. На данный момент у меня есть модель пользователя:CActiveDataProvider с пользовательским значением

public $month_profit; 

public function search($pageSize = 10, $defaultOrder = '`t`.`reg_date` DESC') 
{ 
    $criteria = new CDbCriteria; 
    $criteria->with = array('money'); 
    $requests_table = Requests::model()->tableName(); 
    $requests_count_sql = "(SELECT COUNT(*) FROM $requests_table rt WHERE rt.partner_id = t.id) "; 

    $referrals_table = Referrals::model()->tableName(); 
    $referrals_count_sql = "(SELECT COUNT(*) FROM $referrals_table reft WHERE reft.user_id = t.id) "; 
    $referrals_payed_sql = "(SELECT COUNT(*) FROM $referrals_table reft WHERE reft.user_id = t.id AND reft.status = 'Оплачено') "; 
    //$month profit_sql = ???; 

    $criteria->select = array(
     '*', 
     $requests_count_sql . "as requests_count", 
     $referrals_count_sql . "as referrals_count", 
     $referrals_payed_sql . "as referrals_payed_count", 
     $month_profit_sql . "as month_profit", 
    ); 

    $criteria->compare($requests_count_sql, $this->requests_count); 
    $criteria->compare($referrals_count_sql, $this->referrals_count); 
    $criteria->compare($referrals_payed_sql, $this->referrals_payed_count); 
    $criteria->compare($month_profit_sql, $this->month_profit); 

    $criteria->compare('t.id', $this->id); 
    $criteria->compare('t.reg_date', $this->reg_date, true); 
    $criteria->compare('username', $this->username, true); 
    $criteria->compare('password', $this->password, true); 
    $criteria->compare('site', $this->site, true); 
    $criteria->compare('status', $this->status, true); 

    return new CActiveDataProvider(get_class($this), array(
     'criteria' => $criteria, 
     'pagination' => array('pageSize' => $pageSize), 
     'sort' => array(
      'defaultOrder' => $defaultOrder, 
      'attributes' => array(
       'id' => array(
        'asc' => '`t`.`id` ASC', 
        'desc' => '`t`.`id` DESC', 
       ), 
       'email' => array(
        'asc' => '`t`.`email` ASC', 
        'desc' => '`t`.`email` DESC', 
       ), 
       'requests_count' => array(
        'asc' => 'requests_count ASC', 
        'desc' => 'requests_count DESC', 
       ), 
       'referrals_count' => array(
        'asc' => 'referrals_count ASC', 
        'desc' => 'referrals_count DESC', 
       ), 
       'referrals_payed_count' => array(
        'asc' => 'referrals_payed_count ASC', 
        'desc' => 'referrals_payed_count DESC', 
       ), 
       'money' => array(
        'asc' => 'money.profit', 
        'desc' => 'money.profit DESC', 
       ), 
       'fullProfit' => array(
        'asc' => 'money.full_profit', 
        'desc' => 'money.full_profit DESC', 
       ), 
       '*', 
      ), 
     ) 
    )); 
} 

E.g. У меня есть отношения в моей модели пользователя:

public function relations() 
{ 
    return array(
     'clients' => array(self::HAS_MANY, 'Referrals', 'user_id'), 

Скажем, мой month_profit будет равен: кол-пользователя clients зарегистрировано за последние 30 дней * 150. Мне нужно каким-то образом передать эти данные в search() и создать CDbCriteria для сортировки пользователей по month_profit. Это даже реально? :) Должен ли я создать другую функцию для вычисления всего, а затем перейти к search()? Все мои попытки дошли до отказа до сих пор.

+0

Мне действительно интересно, если мой ответ работал или нет, и каково было решение. –

ответ

0

Я полагаю, что вам нужно что-то вроде следующего, на основе этого руководства http://www.yiiframework.com/wiki/319/searching-and-sorting-by-count-of-related-items-in-cgridview

Сначала сделайте статистический запрос в отношениях в модели пользователя:

'month_profit' => array(self::STAT, 'User', 'id', 'select'=>'COUNT(*) * 150', 'condition'=>'DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= reg_date'), 

Затем отметьте «month_profit» атрибут как безопасные в сценарий поиска в правилах.

public function rules() { 
    return array(

     ... 

     array('username, ... , month_profit', 'safe', 'on' => 'search'), 
    ); 
} 

Добавить все это, где каждый из них необходим в поиске пользователя() метод:

$user_table = User::model()->tableName(); 
$month_profit_sql = "(SELECT COUNT(*) FROM user_table WHERE DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= reg_date)"; 

$criteria->select = array(
    '*', 
    $requests_count_sql . "as requests_count", 
    $referrals_count_sql . "as referrals_count", 
    $referrals_payed_sql . "as referrals_payed_count", 
    $month_profit_sql . "as month_profit", 
); 

... 
$criteria->compare($month_profit_sql, $this->month_profit); 

return new CActiveDataProvider(get_class($this), array(
    'criteria' => $criteria, 
    'pagination' => array('pageSize' => $pageSize), 
    'sort' => array(
     'defaultOrder' => $defaultOrder, 
     'attributes' => array(
      'id' => array(
       'asc' => '`t`.`id` ASC', 
       'desc' => '`t`.`id` DESC', 
      ), 

      ... 

      'month_profit' => array(
       'asc' => 'month_profit ASC', 
       'desc' => 'month_profit DESC', 
      ), 

      '*', 
     ), 
    ) 
)); 

Наконец, измените сетку:

$this->widget('zii.widgets.grid.CGridView', array(
    'dataProvider' => $model->search(), 
    'filter' => $model, 
    'columns' => array(
     'username', 

     ... , 

     'month_profit', 
     array(
      'class'=>'CButtonColumn', 
     ), 
    ), 
)); 

Пожалуйста, дайте мне знать, если это обработанное ,

EDIT Если это не работает, попробуйте его без статистического запроса.