CGridView иjoin нескольких таблиц

Добрый день,

Есть таблица Assets, в которой хранятся ID модели оборудования, поставщика, пользователя и тд.

Нужно вывести таблицу Assets в CgridView так, чтобы вместо ID (vendor, owner, model) было имя (vendor_name, model_name, owner_name) поставщика\юзера или модели, найденное из соответствующей таблицы (Vendor, Owner, Model) по ID.

Также должны быть фильтры search для каждого поля.

Таблицы:

Table Assets:

itemId

vendor (HAS_MANY relations)-> Vendor.vendorId

owner (HAS_MANY relations)-> Owner.ownerId

model (HAS_MANY relations)-> Model.modelId


Table Vendor:

vendorId

vendor_name


Table Owner:

ownerId

owner_name


Table Model

modelId

model_name

Relations in model class:


class Assets extends CActiveRecord

{

	public function relations()

	{		return array(				

'model_rel' => array(self::HAS_MANY, 'Model','','on'=>'model=modelId', 'joinType'=>'INNER JOIN', 'alias'=>'Model'),

'owner_rel' => array(self::HAS_MANY, 'Owner','','on'=>'owner=ownerId', 'joinType'=>'INNER JOIN', 'alias'=>'Owner'),

'vendor_rel' => array(self::HAS_MANY, 'Vendor','','on'=>'vendor=vendorId', 'joinType'=>'INNER JOIN', 'alias'=>Vendor'),	

);

	}

…..

}

Используя данные relations, мне удалось получить выборку из таблиц только таким образом:

View:


<?php


$db = new CActiveDataProvider(

$model->with('vendor_rel', 'model_rel','owner_rel'

);


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

	'id'=>'assets-grid',

	'dataProvider'=>$db,

	'filter'=>$model,

	'columns'=>array(

		'vendor_rel.0.vendor_name',

		'owner_rel.0.owner_name',

		'model_rel.0.model_name',

….

?>

1. Если указать не ‘vendor_rel.0.vendor_name’, а просто ‘vendor_name’, получаю ругань типа property vendor_name is not defined for model Assets. Хотя вроде бы таблицы должны быть заджоинены…

2. Просто ‘model_rel. model_name’ дает пустой столбец, и, вроде, понятно почему (model_rel возвращает массив и нам нужена 1я строка)

3. Фильтров для полей vendor_name, owner_name и тд я не вижу. Тоже понятно почему, ведь

‘filter’=>$model. Но если сделать ‘filter’=>$db, то получу ругань: CActiveDataProvider does not have a method named “getValidators”…

Возможно я чего-то просто не понимаю, и решение лежит на поверхности.

Подскажите пожалуйста, как я могу заджоинить несколько таблиц, связанных не по PK таблицы Assets, выбрать нужные поля из получившегося результата и иметь фильтры для этих полей (как должна выглядеть ф-ция Search)?

Огромное спасибо

Посмотрите на несколько тем ниже в форуме, абсолютно аналогичный вопрос: http://www.yiiframework.com/forum/index.php?/topic/21323-cgridview-и-join-search-order-для-новичка/

Возможно, мой ответ будет вам более понятен, чем автору той темы, но он вроде всё-таки как-то решил этот вопрос по-своему.

Спасибо, я видел топик, но, к сожалению, проблемы не решил.

Если сделать следующий search


public function search()

	{

	$criteria=new CDbCriteria;

	$criteria->with = array('type_rel','brand_rel','model_rel');

	$criteria->compare('type_rel.type_name', $this->type_name, true);

	$criteria->compare('brand_rel.brand_name', $this->brand_name, true);

	$criteria->compare('model_rel.model_name', $this->model_name, true);


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

        'criteria'=>$criteria));

}

И попробовать построить таблицу с нужными полями:


<?php


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

	'id'=>'items-grid',

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

	'filter'=>$model,

	'type_rel.type_name',

	'model_rel.model_name',

	'brand_rel.brand_name',

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

	)

);

}

Получаю:

Property "Assets.type_name" is not defined.

Мне не очень понятно, как обращаться к полям присоединенных таблиц. Постоянно идут попытки искать запрашиваемые поля в таблице Assets почему-то.

Если не сложно, подскажите пожалуйста, голову уже сломал.

Вызов виджета должен быть примерно следующим:




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

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

    'filter'=>$model,

    'columns'=>array(

        array(

            'type'=>'raw',

            'name'=>'type_name',

            'value'=>'$data->type_rel->type_name',

        ),



При этом в модель нужно дополнительно добавить атрибут type_name, а в методе search() указать:




$criteria->compare('<псевдоним таблицы>.type_name', $this->type_name, true);



Соответственно атрибут type_name должен быть отмечен как "safe" при поиске. Этот атрибут нужен для того, чтобы было чему присваивать значение из грида при поиске. Сейчас у вас его нет. Конечно, это не очень красиво добавлять какие-то сторонние атрибуты в модель, но других способов я не знаю.

Понятно, просто пустые поля для присваивания значений из другой модели.

Большое спасибо, я попробую.