Фильтр в GridView по связанной модели hasMany

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
nickdenry
Сообщения: 99
Зарегистрирован: 2015.10.28, 04:55

Фильтр в GridView по связанной модели hasMany

Сообщение nickdenry »

Доброго времени суток!

Интересует такой вопрос - имеется 2 связанные модели

Customer и CustomerPhone,

через

Код: Выделить всё

модель Customer.php
/**
  * @return \yii\db\ActiveQuery
  */
  public function getCustomerPhones()
  {
      return $this->hasMany(CustomerPhone::className(), ['customer_id' => 'id']);
  } 
И GridView в index.php CRUD, в котором телефоны выводятся в цикле:

Код: Выделить всё

<?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
                'id',
                [
                    'attribute' => 'phones',
                    'format' => 'html',
                    'label' => 'Телефоны',
                    'value' => function ($model) {
                        $phones = '';
                        foreach ($model->customerPhones as $key => $phone) {
                            if ($key !== 0) {
                                $phones .= '<br />';
                            }
                            $phones .= Html::a($phone['number'], ['/customer/view', 'id' => $model['id']]);
                        }
                        return $phones;
                    },
                ],
                [
                    'attribute'=>'name',
                    'label'=>'ФИО',
                ],
                [
                'class' => 'yii\grid\ActionColumn',
                'header'=>'Действия',
                ],
        ],
    ]); ?>

Возможно ли организовать фильтрацию по введенному в фильтр телефону? Если да, подскажите, какие образом?

В SQL это могло бы выглядеть следующим образом:

Код: Выделить всё

SELECT * FROM `customer` LEFT JOIN `customer_phone` on `customer`.`id` = `customer_phone`.`customer_id` WHERE `customer_phone`.`number` LIKE '%987%' 

Нужен именно текстовый поиск. Примерно понимаю, что копать нужно в сторону search model, но пока не понимаю, возможно ли это вообще?
Последний раз редактировалось nickdenry 2015.10.29, 03:06, всего редактировалось 1 раз.
Ответственные программисты с высоким уровнем технического долга (c)
nickdenry
Сообщения: 99
Зарегистрирован: 2015.10.28, 04:55

Re: Фильтр в GridView по связанной модели hasMany

Сообщение nickdenry »

Спасибо, разобрался!

1. В search model CustomerSearch добавил поле 'phones' как safe

Код: Выделить всё

public function rules()
{
    return [
        [['id'], 'integer'],
        [['name',  'phones' /* тут */,  'created_at', 'updated_at'], 'safe'],
    ];
}
по связи

Код: Выделить всё

модель Customer.php
/**
 * @return \yii\db\ActiveQuery
 */
  public function getCustomerPhones()
  {
      return $this->hasMany(CustomerPhone::className(), ['customer_id' => 'id']);
  }
2. и в public function search($params) добавил query следующего вида к $dataProvider (смог отстроить методом проб и ошибок по запросу)

Код: Выделить всё

   $query->joinWith(['customerPhones' => function ($q) {
       $q->where('`customer_phone`.number LIKE "%' . $this->phones . '%"');
    }]);
Все заработало.

Изображение

Остается неясным один вопрос - почему в index.php CRUD (gridview 'attribute' => 'phones') и в public function rules()) поле указывается как "phones", а не "customerPhones".

В $query->joinWith(['customerPhones' - как я понял, 'customerPhones' - это ссылка на метод модели $customer->getCustomerPhones(), а вот почему в datagrid (и public function rules()) колонка называется просто phones - и откуда вообще берется? Подскажите пожалуйста.
Ответственные программисты с высоким уровнем технического долга (c)
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Фильтр в GridView по связанной модели hasMany

Сообщение vitalik1183 »

Код: Выделить всё

В $query->joinWith(['customerPhones' - как я понял, 'customerPhones' - это ссылка на метод модели $customer->getCustomerPhones() 
верно поняли
а вот почему в datagrid (и public function rules()) колонка называется просто phones - и откуда вообще берется? Подскажите пожалуйста.
ну видимо у вас так называется одно из полей. в рулезах идет перечисление полей с указанием применяемого валидатора.
Yii2!
nickdenry
Сообщения: 99
Зарегистрирован: 2015.10.28, 04:55

Re: Фильтр в GridView по связанной модели hasMany

Сообщение nickdenry »

@vitalik1183
ну видимо у вас так называется одно из полей. в рулезах идет перечисление полей с указанием применяемого валидатора.
Спасибо. Про rules понятно, непонятно где указывается так поле -

модели - Customer, CustomerPhones, таблицы соотвественно customer, customer_phones, - метод в модели Customer - getCustomerPhones, - а вот отдельно phones нигде не прописан. Хотелось бы понять принцип образования.
Ответственные программисты с высоким уровнем технического долга (c)
zei
Сообщения: 1
Зарегистрирован: 2016.11.11, 16:42

Re: Фильтр в GridView по связанной модели hasMany

Сообщение zei »

у вас в атрибутах колонки grid указан 'attribute' => 'phones', там он и образуется
Ответить