CGridView и join, search, order для новичка.

CGridView подкиньте плиз код реально работает join, search, order. :)

Это совсем не много, так как это должно быть в любой таблице.

Вот например


 public function relations()

    {

        // NOTE: you may need to adjust the relation name and the related

        // class name for the relations automatically generated below.

        return array(

            'category' => array(self::BELONGS_TO, 'Category', 'category_id'),

        );

    }


    public function search()

    {

      $criteria=new CDbCriteria;


                $criteria->with=array(

                    'category',

                );


        return new CActiveDataProvider('Articles', array(

            'criteria'=>$criteria,

        ));

    }

тут похоже, но не хватает кучи информации, как это дело воспроизвести, приходится подбирать на угад.

Пытаюсь идти от стандартной формы которую создаю через конструктор, добавляю туда сцепленные столбцы, но

  1. Не отображается поле поиска над столбиками из другой таблицы.

  2. Нет в поиске этих столбцов.

  3. Очень много вариантов сцепления и все работают не верно, не могу поймать логику людей сделавших фреймворк, чем они руководствовались когда делали таблицы которые не работают нормально с джойнами. Если бы были нормальные таблицы, в интернете было бы полно примеров, но увы все примеры или слишком сложны, то есть требуют более высокого уровня, при котором можно самому писать фреймворк или слишком просты и в них нет того, что интересует именно меня.

Есть ли у кого нибудь простой пример сцепления двух таблиц через BELONGS_TO в модели? Но с поиском над сцепленными столбцами и без ошибок SQL запросов в момент вывода на экран после поиска?

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

Метод search:




public function search($itemPerPage=25)

{

    $criteria = new CDbCriteria;

    

    $criteria->with = array('user');

    $criteria->compare('users.full_name', $this->search_user, true);


    $criteria->compare('orders.order_id', $this->order_id);

    $criteria->compare('orders.item_count', $this->item_count);

    $criteria->compare('orders.price', $this->price);

    $criteria->compare('orders.status', $this->status);

    $criteria->compare('orders.date', $this->date, true);


    return new CActiveDataProvider(get_class($this), array(

        'criteria'=>$criteria,

        'pagination'=>array(

            'pageSize'=>$itemPerPage,

        ),

    ));

}



Часть конфига CGridView (раздел columns):




array(

    'type'=>'raw',

    'name'=>'search_user',

    'value'=>'CHtml::link($data->user->full_name, array("/user/user/update", "id"=>$data->user->user_id))',

    'htmlOptions'=>array('style'=>'text-align: center;'),

),



В модель нужно было добавить атрибут search_user и сделать его ‘safe’ при поиске.

Надеюсь, это поможет, а на Yii Framework не жалуйтесь, нехорошо это ;)

andy_s Спасибо но это мне не поможет, все таки вырвано из контента, нет структуры базы.

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

В итоге получается что отображаются в поле то что нужно, а поиск происходит не по нужному тексту связанному с ID а по ID.

B и это я еще не начал пытаться переделать на нее сложный джойн а только два поля связываю.

Где то я видел как это обходили, очень наворочено.

Ну основные идеи здесь уловить можно:

  1. Добавить в модель доп. поле, которое будет отображаться в гриде и по которому нужен поиск.

  2. Сделать поле безопасным при поиске (safe on search).

  3. В методе search добавить две строчки (у меня после new CDbCriteria) по аналогии…

Вот тут мне помогли на другом форме, ссылку не могу дать, форум запрещает, мощная защита. :D

Все таки мой уровень не позволяет понимать такие вещи на словах, нужны реальные примеры, я совсем незнаю Yii, начал его изучение как раз с CGridView.

Боязно конечно, если будет много сложных таблиц и они начнут выдавать ошибки при поиске и т.д.

А через CDbCriteria + join тут никак только модели AR?

Вот что мне помогло, файл из цельного примера.

Кому нужно, ищите в поисковиках, по кускам приведенного кода, найдется.


CREATE TABLE `city` (

  `id` int(11) NOT NULL auto_increment,

  `name_city` varchar(64) NOT NULL,

  PRIMARY KEY  (`id`)

) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=4 ;


INSERT INTO `city` VALUES (1, 'Москва');

INSERT INTO `city` VALUES (2, 'Санкт-Петербург');

INSERT INTO `city` VALUES (3, 'Выборг');


CREATE TABLE `name` (

  `id` int(11) NOT NULL,

  `name_person` varchar(64) NOT NULL,

  `id_city` int(11) NOT NULL,

  PRIMARY KEY  (`id`),

  KEY `id_city` (`id_city`)

) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


INSERT INTO `name` VALUES (0, 'Иван', 1);

INSERT INTO `name` VALUES (1, 'Михаил', 2);

INSERT INTO `name` VALUES (2, 'Алексей', 3);

INSERT INTO `name` VALUES (3, 'Вячеслав', 2);

INSERT INTO `name` VALUES (4, 'Даша', 1);

Модель Name


class name extends CActiveRecord

{

    /**

     * The followings are the available columns in table 'name':

     * @var integer $id

     * @var string $name_person

     * @var integer $id_city

     */

    

    /**

     * Returns the static model of the specified AR class.

     * @return CActiveRecord the static model class

     */

    public static function model($className=__CLASS__)

    {

        return parent::model($className);

    }


    /**

     * @return string the associated database table name

     */

    public function tableName()

    {

        return 'name';

    }

    

    public function rules()

    {

        return array(

            // The following rule is used by search().

            array('id, name_person, nameCity, nameCity1', 'safe', 'on'=>'search'),

        );

    }

    

    public function attributeLabels()

    {

        return array(

            'id' => 'Id',

            'name_person' => 'Name',

            'nameCity' => 'City',

            'nameCity1' => 'City1',

        );

    }

    

    /**

     * Отношения name с другими таблицами

     */

    public function relations()

    {

        return array(

            'nameCity'=>array(self::BELONGS_TO, 'city', 'id_city'),

            'nameCity1'=>array(self::BELONGS_TO, 'city', 'id_city'),

        );

    }

    

    /**

     * Retrieves a list of models based on the current search/filter conditions.

     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

     */

    public function search()

    {

        $criteria=new CDbCriteria;

        $criteria->compare('t.id',$this->id);

        $criteria->compare('name_person',$this->name_person,true);

        

        $criteria->with=array('nameCity','nameCity1'); // жадная загрузка

        //$criteria->with=array('nameCity1'); // жадная загрузка

        $criteria->compare('nameCity.name_city',$this->nameCity,true); // поиск по связанному полю

        $criteria->compare('nameCity1.name_city',$this->nameCity1,true); // поиск по связанному полю

        

        return new CActiveDataProvider('name', array(

            'criteria'=>$criteria,

            'sort'=>array('attributes'=>array(

                'nameCity'=>array( // сортировка по связанном полю

                    'asc' => $expr='nameCity.name_city',

                    'desc' => $expr.' DESC',

                ),

                'nameCity1'=>array( // сортировка по связанном полю

                    'asc' => $expr='nameCity1.name_city',

                    'desc' => $expr.' DESC',

                ),

                'id'=>array( // сортировка по id 

                    'asc' => $expr='t.id', // t.id написано потому что у нас id есть в двух таблицах

                    'desc' => $expr.' DESC',

                ),

                'name_person', // не требует подробного описания т.к. это поле индивидуально для двух таблиц

            )),

            'pagination'=>array(

                'pageSize'=>40, // количество записей на странице

            ),

        ));

    }

}

View


$this->widget('zii.widgets.grid.CGridView', array(

    'id'=>'name-grid',

    'dataProvider'=>$model->search(),

    'filter'=>$model,

    'columns'=>array(

        'id',

        'name_person',

        array(

            'name'=>'nameCity',

            'value'=>'$data->nameCity->name_city',

            'sortable'=>true,

        ),

        array(

            'name'=>'nameCity1',

            'value'=>'$data->nameCity1->name_city',

            'sortable'=>true,

        ),

        array(

            'class'=>'CButtonColumn',

        ),

    ),

));

Только не бейте… не подскажите как сделать возможность выбора, чтобы в интерфейсе был выбор 10,20 или 30…?

pagination’=>array(

        'pageSize'=>$itemPerPage,


    ),

Посмотрите реализацию тут: http://www.yiiframework.com/extension/pagesize

спасибо за помощь, вопрос можно же файл pagesize поменять чтобы не droplist а ссылки были на те 20…30?

Судя по тому, что в расширении предлагают эти опции прописать в главном конфиге сайта в разделе params, я бы вообще написал свой виджет на базе этого (в который можно непосредственно передавать все параметры) и пользовался на здоровье :)