@dro1d

Как сделать фильтрацию и сортировку данных из смежных таблиц в Yii1?

Есть Yii1. В ней 2 модели Users(id,name,surename) и Contacts(id,phone,email). Связь между моделями 1 к 1.
В модели users связь описана так:
public function relations()
	{
		return array(
			'contacts'=>array(self::HAS_ONE, 'contacts', 'id'),
		);
	}

Во вьюхе admin у users в стандартный виджет zii.widgets.grid.CGridView добавляю следующий элемент в 'columns':
'phone'=>array( 
			'name'=>'User phone',
			'value'=>'$data->contacts->phone',
		),

В итоге получаю следующую ошибку:
73ca0bbe58af41bb8facdc789e0e883a.png
Если добавить одну строчку:
'phone'=>array( 
			'name'=>'User phone',
			'value'=>'$data->contacts->phone',
			'filter'=>true,	
		),

Получаем:
1e4fef55d3154017b5d38d9a1401f612.png
Как сделать так, чтоб по этим полям была доступна полноценная фильтрация и поиск?
Спасибо.
  • Вопрос задан
  • 300 просмотров
Решения вопроса 1
@Cage
Первый вариант не работал потому что при рендере фильтра он пытался обратиться к свойству "User phone" модели Users, как вы понимаете такого свойства нет.
Во втором случае он не обращается к св-ву потому что вы ему явно прописали значение filter, кстати неправильно - там должен быть html код.
В данном случае лучше действовать так:
1 . В модели Users добавьте св-во (именно св-во класса а не поле в БД) phone,
class Users extends CActiveRecord {
  public $phone;
  ...
}


2. Пропишите его в методе rules() класса Users
['phone','safe', 'on' => 'search']

3. в настройках виджета используйте следующую конструкцию для этой колонки
[
  'header'=>'Здесь заголовок колонки',
  'value'=>function($data){ return $data->contacts->phone;} // или просто '$data->contacts->phone',
  'filter'=>CHtml::activeTextField($model,'phone')
],


4. В методе search класса Users добавьте следующий код
if ($this->phone){
  $criteria->with[] = 'contacts';
  $criteria->compare('contacts.phone', $this->phone) // третьим параметром добавьте true если будете искать неполное совпадение
}


Теперь объяснение всей этой лабуды
1. Свойство в модели необходимо для хранения значения когда будет использоваться поиск.
2. Добавление св-ва в метод rules необходимо для безопасного присваивания атрибута, это когда в экшене вы будете делать так
$model = new Users('search');
if (array_key_exists('Users', $_GET)){
  $model->attributes = $_GET['Users'];
}

3. Виджет на самом деле настраивается очень гибко там может быть много вариантов я написал один из них как самый простой, для понимания как рендерится фильтр можно посмотреть метод CDataColumn::getFilterCellContent() например можно было бы использовать и следующую конструкцию:
[
  'name'=>'phone',
  'value'=>function($data){ return $data->contacts->phone;} // или просто '$data->contacts->phone',
],

4. Собственно это реализация поиска по номеру телефона. могут быть и другие варианты реализации, но этот самый правильный и удобный.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы