понедельник, 10 декабря 2012 г.

Легкая сортировка данных из БД

Для одного из проектов потребовалась сортировка по полям таблицы. Задача как понимаю типичная и многим приходиться её решать от проекта к проекту. В Yii для этого существует класс CSort, но к сожалению нормального описания в примерах я так и не нашел. --- Пошуршав немного на форуме была обнаружена тема « my gripes with CSort (and solution) » где автор делится своим маленьким, но очень интересным классом на основе CSort. Мне показалась работа автора очень интересной и я решил описать её в этой статье. Настройка Первым делом создадим файл «protected/components/CActiveSort.php»


model = CActiveRecord::model($modelName);
    
    $this->aliases = is_callable(array($this->model, 'sorts')) ? $this->model->sorts() : array();
    
    if (isset($_GET['sort'])) {
      $bits = explode($this->separator, $_GET['sort']);
      if ($this->getAlias($bits[0])) $this->current = $bits[0];
      if (isset($bits[1]) && $bits[1] == 'desc') $this->current_ascend = false;
    }
    
  }
  
  protected function getAlias($alias) {
    
    if (!isset($this->aliases[$alias])) {
      $attributes = $this->model->attributeNames();
      if (in_array($alias, $attributes)) {
        $this->aliases[$alias] = $alias;
      } else {
        return null;
      }
    }
    
    $config = $this->aliases[$alias];
    
    if (is_string($config)) {
      $this->aliases[$alias] = array(
        'asc'=>$config.' asc',
        'desc'=>$config.' desc'
      );
    }
    
    return $config;
    
  }
  
  public function applyOrderTo($criteria) {
    
    $config = $this->getAlias($this->current);
    if (!$config) return;
    
    $criteria->order = $config[$this->current_ascend ? 'asc' : 'desc'];
    
  }
  
  public function link($alias, $label=null, $htmlOptions=array()) {
    
    if (is_null($label))
      $label = $this->model->getAttributeLabel($alias);
    
    $config = $this->getAlias($alias);
    
    if (!$config)
      return CHtml::encode($label); # non-sortable
    
    $controller = Yii::app()->getController();
    
    $ascend = ( $alias != $this->current ? false : $this->current_ascend );
    
    $params = $_GET;
    $params[$this->paramName] = $alias . $this->separator . ($ascend ? 'desc' : 'asc');
    
    $url = $controller->createUrl($this->route, $params);
    
    $class = $alias == $this->current ? ($ascend ? 'sort-asc' : 'sort-desc') : 'sort-none';
    $htmlOptions['class'] = (isset($htmlOptions['class']) ? $htmlOptions['class'].' ' : '') . $class;
    
    return CHtml::link($label, $url, $htmlOptions);
    
  }
  
}
Для подключения в контроллере понадобится от силы 5 секунд т.к. вся логи у нас будет в модели. Вот так происходит подключение сортировки для контроллера:
count($criteria));
                $pages->pageSize=self::PAGE_SIZE;
                $pages->applyLimit($criteria);
    
                // а вот и работа с нашим классом сортировки
                // всего две строчки!
                $sort = new CActiveSort('UserLog');
                $sort->applyOrderTo($criteria);
                
                $models = UserLog::model()->withNames()->findAll($criteria);

                $this->render('browse',array(
                        'models'=>$models,
                        'pages'=>$pages,
                        'sort'=>$sort,    
// обязательно передаем $sort в отображение
                ));
        }
  
}
В view файле мы создаем заголовок таблицы с полями по которым будем сортировать (аналогично CSort)

Логи

...
link('id', 'ID'); ?> link('entry_type'); ?> link('client','Client'); ?> link('user','User Name'); ?> link('text'); ?> link('logged'); ?>
Ну и самое интересное — это настройка сортировки в вашей модели:
 array('asc'=>'user.first_name asc, user.last_name asc', 'desc'=>'user.first_name desc, user.last_name desc'),
      'client' => 'client.name',
      'id' => 'userlog.id'
    );
  }

}
Этот пример показывает как создать сложные сортировки (user) и простые по полям в базе (client, id). Простые сортировки автоматически добавляют «asc» и «desc», для сложных — требуется описывать самостоятельно (как в примере с user) что бы иметь возможность создавать более сложные и уникальные виды сортировок. Реальный пример Вот пример того как сортировка работает в одном из моих проектов. protected/models/User.php:
 'Номер',
            'login'         => 'Логин',
            'hash'            => 'Хеш'
        );
    }
    public function sorts() {
        return array(
          'id'             => 'id',
          'hash'         => 'hash',
          'login'         => 'login',
        );
    }
}
protected/controllers/IndexController.php:
order = 'id DESC';

        $sort = new CActiveSort('User');
        $sort->applyOrderTo($criteria);

        $users = User::model()->findAll($criteria);
        
        $this->render('sort', array(
                    'users' => $users, 
                    'sort' => $sort,
        ));
    }

}
protected/views/index/sort.php:

 <table border="1" class="list dataGrid">
  
 

    "50"


> echo $sort->link('id', '#'); ?>    
"50"
> echo $sort->link('hash', 'hash'); ?>     "50"
> echo $sort->link('login', 'login'); ?>     if (!empty($users)) {     foreach ($users as $key => $val) {         ?>                      $val
->id?>             $val
->hash?>             $val
->login?>         ?>

Комментариев нет:

Отправить комментарий