Сортировка по полю не из бази

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
suchUser
Сообщения: 7
Зарегистрирован: 2013.06.12, 17:48

Сортировка по полю не из бази

Сообщение suchUser » 2013.07.16, 11:14

Здраствуйте!
Прошу помощь в сортировке.

Допустим у меня есть таблица User и я хочу отобразить таблицу(в вюшке), но там должна бить колонка Баланс, которая немножко сложно рассчитывается (Yii::app()->getModule("billing")->getBalance($this->id), где $this->id - id user).

Как сделать рортировку в таком случае?

п.с. да, я искал, но везде показано вычисления с помощью SQL.
здесь https://github.com/yiisoft/yii/issues/194 пишут, что надо юзать CArrayDataProvider, но в нем недостаток, как я понял, надо тянуть все з бази, но если будет много записей... ето плоха идея.. (это обясняєтсья здесь http://www.yiiframework.com/forum/index ... _p__208969)

Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Сортировка по полю не из бази

Сообщение lancecoder » 2013.07.16, 12:44

выражайтесь яснее, вы хотите сделать рортировку не из бази, без датапровайдра, если я все верно понял, тогда вам нужен CGort компонент

Аватара пользователя
Barssoft
Сообщения: 726
Зарегистрирован: 2013.01.21, 16:03

Re: Сортировка по полю не из бази

Сообщение Barssoft » 2013.07.16, 13:16

Аналогичный вопрос, вот смотрите я использую класс CActiveDataProvider, на основе его данных строиться грид, в гриде есть колонка где написано

Код: Выделить всё

 array(
        'name'=>'time_wait',
        'value'=>'$data->getTime($data->date_create,$data->date_end, $data->status)'
        ), 
Данного поля в базе нет, так публичная переменная в модели, функция в модели выглядит так

Код: Выделить всё

     public function getTime($time_in,$time_end,$status) {
        
        if($status==2){  ;
           $time =$time_end-($time_in+6*3600);
           return date('H:i:s',$time);
        }else{
           return date('H:i:s',time()-($time_in+6*3600)); 
        }
        
        
     } 
как сделать сортировку по получившейся колонки, а то она не активна...

suchUser
Сообщения: 7
Зарегистрирован: 2013.06.12, 17:48

Re: Сортировка по полю не из бази

Сообщение suchUser » 2013.07.16, 13:31

аналогично с предыдущим постом

мне нужно отобразить таблицу с сортировокй по всем полям, где поля

Пользователи
# имя e-mail баланс
1 .... ....... 15
2 .... ....... 78

и где колонка баланс не является полем таблицы User а просто подсчитывается (не с помощью SQL запроса!). Как это лучше зделать?

Аватара пользователя
Neuromance
Сообщения: 716
Зарегистрирован: 2011.09.06, 13:04

Re: Сортировка по полю не из бази

Сообщение Neuromance » 2013.07.16, 13:40

Barssoft, насколько я знаю, поля заданные не по name, а по value не могут быть отсортированы и отфильтрованы стандартными средствами. Чтобы сортировать или фильтровать такие поля вам надо или value вычислять в наследнике CFormatter, а колонке задавать соответствующий type, или все нужные поля вычислять заранее в запросе к БД, или переопределять и допиливать dataProvider для ваших целей

suchUser
Сообщения: 7
Зарегистрирован: 2013.06.12, 17:48

Re: Сортировка по полю не из бази

Сообщение suchUser » 2013.07.16, 13:52

может где-нибудь есть пример?

Аватара пользователя
Barssoft
Сообщения: 726
Зарегистрирован: 2013.01.21, 16:03

Re: Сортировка по полю не из бази

Сообщение Barssoft » 2013.07.16, 13:53

Neuromance писал(а):вычислять в наследнике CFormatter, а колонке задавать соответствующий type,
есть пример как это делать

Аватара пользователя
Neuromance
Сообщения: 716
Зарегистрирован: 2011.09.06, 13:04

Re: Сортировка по полю не из бази

Сообщение Neuromance » 2013.07.16, 14:05

в компоненты запихиваешь класс YourFormatter extends CFormatter.
в конфиге

Код: Выделить всё

'components'=>array(
  'format'=>array(
    'class'=>'YourFormatter'
   ),
В этом классе объявляешь функции преобразования данных к нужному формату.
Например, вот у меня получение даты-времени из мсекунд.

Код: Выделить всё

public function formatDatetimeFromMs ($value){
    if(!$value) 
      return null;
    return date("d.m.Y H:i:s", $value);;
}
В нужной колонке указываешь тип

Код: Выделить всё

array(
        'name'=>'time_wait',
        'type'=>'datetimeFromMs'
        ), 
Barrsoft, это всё не подходит для твоего примера, т.к. ты там используешь для получения нужного значение разные колонки из $data

Аватара пользователя
Barssoft
Сообщения: 726
Зарегистрирован: 2013.01.21, 16:03

Re: Сортировка по полю не из бази

Сообщение Barssoft » 2013.07.16, 14:07

Очень очень жаль ((( так хотелось чтоб сортировка работала

Аватара пользователя
SiZE
Сообщения: 2698
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Сортировка по полю не из бази

Сообщение SiZE » 2013.07.16, 14:42

Сделай вычисляемое поле или напиши функцию/процедуру. За одно будет больше контроля на уровне БД. А лушче таблицу, в которой будет хранится значение и пересчитываться только при необходимости. Делов то.
в поиске работы

Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Сортировка по полю не из бази

Сообщение lancecoder » 2013.07.16, 16:19

sql data provider же есть

suchUser
Сообщения: 7
Зарегистрирован: 2013.06.12, 17:48

Re: Сортировка по полю не из бази

Сообщение suchUser » 2013.07.17, 16:04

lancecoder писал(а):sql data provider же есть
покажите пожалуйста пример, как с помощью sql data provider сделать сортировку по полю не из бази.

Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Сортировка по полю не из бази

Сообщение lancecoder » 2013.07.17, 16:09

вам либо баланс вычислять sql запросом, если это не возможно, то сортировка будет трудозатратной, ибо придется выбрать все записи, сделать в критерии индексом геттер на досчет баланса, а потом пхп сортировать массив. Неверно реализовали структуру БД

Аватара пользователя
ElisDN
Сообщения: 5428
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Сортировка по полю не из бази

Сообщение ElisDN » 2013.07.17, 20:59

Для работы сортировки по выражению

Код: Выделить всё

array(
    'name'=>'time_wait',
    'value'=>'$data->getTime($data->date_create,$data->date_end, $data->status)'
), 
сделайте в модели геттер для time_wait для вывода в ячейке:

Код: Выделить всё

class MyModel extends CActiveRecord
{
    public function getTime_wait() {
        if ($this->status == 2) {
            $end =  $this->date_end;
        } else {
            $end = time();
        }
        return date('H:i:s', $end - $this->date_create - 6*3600);
    }
    public function attributeLabels() {
        return array(
            ...
            'time_wait'=>'Время',
        );
    }
} 
и методе search этой же модели добавьте, как уже предлагали, вычисляемое поле в секцию SELECT запроса для сортировки:

Код: Выделить всё

$criteria->select = '*, IF(status=2, date_end - date_create - 6 * 3600, NOW() - date_create - 6 * 3600) AS time_wait';
...
$dataProvider = new CActiveDataProvider('MyModel', array(
    'criteria'=>$criteria,
    'sort'=>array(
        'attributes'=>array(
            'id',
            'title',
            'time_wait',
        ),
    ),
)); 
Теперь в гриде выводите по имени свойства:

Код: Выделить всё

array(
    'id',
    'title',
    'time_wait',
), 
Для отображения будет вызываться геттер и в ячейке будет результат H:i:s, и будет работать сортировка.

Ответить