DbHelp.ru
Маленький Yii блог
Комментарии
Гость: wh0cd2594827 [url=http://pyridium911.us.com/]Pyridium[/url] [url=http://clozaril911.us.org/]clozaril...
Гость: order Retrovir in USA delivery NO PRESCRIPTION ; low prices Retrovir in Canada pharmacy without ...
Гость: wh0cd3078423 [url=http://sildenafil04.us.org/]sildenafil citrate generic[/url] [url=http://xenical02...
Гость: wh0cd2594827 [url=http://dapoxetine911.us.com/]dapoxetine[/url] [url=http://lisinopril03.us.com/]40 ...
Гость: buy essays essay buying order essay now https://buyessay.us.com - college essay helper



Сервер Ultima Online - Forest Wars (от создателя данного блога)

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

Рубрика: Мелкие заметки на тему Yii

Оцените эту статью:

Рейтинг: 0.00 (0)
21 Авг. 2010
Опубликовать в Twitter Написать в Facebook Опубликовать в своем блоге livejournal.com

Для одного из проектов потребовалась сортировка по полям таблицы. Задача как понимаю типичная и многим приходиться её решать от проекта к проекту. В Yii для этого существует класс CSort, но к сожалению нормального описания в примерах я так и не нашел.

---

Пошуршав немного на форуме была обнаружена тема « my gripes with CSort (and solution) » где автор делится своим маленьким, но очень интересным классом на основе CSort.

Мне показалась работа автора очень интересной и я решил описать её в этой статье.

Сразу даю ссылку на результат - смотреть демо

Настройка

Первым делом создадим файл «protected/components/CActiveSort.php»

<?php

class CActiveSort extends CComponent {
 
  public $separator = '-';
  public $paramName = 'sort';
  public $route = '';
 
  protected $aliases;
  protected $model;
 
  protected $current, $current_ascend = true;
 
  public function __construct($modelName) {
    
    $this->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 секунд т.к. вся логи у нас будет в модели. Вот так происходит подключение сортировки для контроллера:

<?php
class UserlogController extends CController
{
        const PAGE_SIZE=50;
        public $defaultAction='browse';
        private $_model;

        public function actionBrowse()
        {
                $criteria=new CDbCriteria;

                // обычная постраничка, с ней вы должны уже быть знакомы
                $pages=new CPagination(UserLog::model()->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)

<h1>Логи</h1>

<table class="dataGrid">
  <thead>
  <tr>
    <th><?php echo $sort->link('id', 'ID'); ?></th>
    <th><?php echo $sort->link('entry_type'); ?></th>
    <th><?php echo $sort->link('client','Client'); ?></th>
    <th><?php echo $sort->link('user','User Name'); ?></th>
    <th><?php echo $sort->link('text'); ?></th>
    <th><?php echo $sort->link('logged'); ?></th>
  </tr>
  </thead>
  <tbody>
...

Ну и самое интересное — это настройка сортировки в вашей модели:

<?php

class UserLog extends CActiveRecord
{
  ...
 
  /**
   * @return array sorting aliases for use with CActiveSort
   */
  public function sorts() {
    return array(
      'user' => 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:

<?php
class User extends CActiveRecord
{
    public static function model($className=__CLASS__)    {
        return parent::model($className);
    }

    public function tableName()    {
        return '{{users}}';
    }

    public function rules()    {
        return array(
            array('login, hash', 'safe'),
        );
    }
    public function attributeLabels() {
        return array(
            'id'            => 'Номер',
            'login'         => 'Логин',
            'hash'            => 'Хеш'
        );
    }
    public function sorts() {
        return array(
          'id'             => 'id',
          'hash'         => 'hash',
          'login'         => 'login',
        );
    }
}

protected/controllers/IndexController.php:

<?php
class IndexController extends Controller
{
    public function actionSort() {
        
        $criteria=new CDbCriteria;
        $criteria->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">
  <thead>
  <tr>
    <th width="50"><?php echo $sort->link('id', '#'); ?></th>
    <th width="50"><?php echo $sort->link('hash', 'hash'); ?></th>
    <th width="50"><?php echo $sort->link('login', 'login'); ?></th>
  </tr>
  </thead>
<?php
if (!empty($users)) {
    foreach ($users as $key => $val) {
        ?>
        <tr>
            <td><?=$val->id?>
            <td><?=$val->hash?>
            <td><?=$val->login?>
        <?
    }
}
?>
</table>

 

Ссылки



Если хотите опубликовать этот материал у себя - пожалуйста, разместите ссылку на страницу откуда вы его взяли.
Другие yii статьи:

  1. Очень долго у меня в голове летает мысль создания собственной хостинг компании. Моим основным заработком уже пол года является чистый ... "#01 : Введение"

  2. Ох много времени я потратил на настройку своего блога на новом хостинге. Получилось так что я взял вдс с isp ... "Проблемы с ЧПУ yii + isp"

  3. Эта статья устарела т.к. была написана для yii версии 1.0.х; Если вы используете более новую версию - у вас могут ... "Настройка 3d капчи на Yii"

[adm] zolter

Было сказано: Суббота, 21 Август 2010

На днях использовал в своем проекте, не мог не поделится :)

[guest] Гость

Было сказано: Воскресенье, 22 Август 2010

А почему бы не использовать решения на js (sorter.js к примеру). Великолепно сортируются таблицы размером 250х20 полей. А исходную выборку мы можем закэшировать.

[guest] zolter

Было сказано: Воскресенье, 22 Август 2010

Данное решение отлично работает вместе с постраничным листанием данных. В случае js вариантов придется делать выборку сразу всех элементов, кешировать их и только потом с ними работать. А что если это 1 млн записей? :)

[guest] junqed

Было сказано: Воскресенье, 22 Август 2010

Хоть в документации мало примеров, зато есть сам исходник - можно посмотреть как этот класс работает. Я так и сделал :)

[guest] zolter

Было сказано: Воскресенье, 22 Август 2010

Иногда на это нет времени :)
Обычно тоже так и капаю когда есть время пошуршать исходниками

[guest] Гость

Было сказано: Воскресенье, 22 Август 2010

вроде всё сделал правильно но почемуто выдаёт ошибку

Не определено свойство "CActiveSort.modelClass".

стоит Yii 1.1.3

[guest] Гость

Было сказано: Понедельник, 23 Август 2010

сейчас переделал, сделал без CActiveDataProvider ошибка пропала

[guest] Ekstazi

Было сказано: Понедельник, 23 Август 2010

Привет, состыковаться можем ? Спишемся ? Моя аська - 7306857. Есть пару вопросов.

[guest] zolter

Было сказано: Понедельник, 23 Август 2010

Давай в скайп - zolter.od

[guest] Гость

Было сказано: Воскресенье, 07 Апрель 2013

Здраствуйте. Отличная статья! А можно какнибудь задать класс для html/css, по умолчанию там стоит class="sort-none"

[guest] Гость

Было сказано: Вторник, 06 Август 2013

жутко не удобно листать в низ особенно даже после ошибок заполнения

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


Код:
Имя: