Inviseble_Demon
@Inviseble_Demon
PHP 15+ лет... к сожалению ^_^

Yii2 3 таблицы связь многие ко многим в GridView::widget реализовать поиск?

Есть 3 таблицы
79200eeab612436995e23b53c6212659.jpg

Таблица обьектов
CREATE TABLE `objects` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`user_id` INT(11) NOT NULL DEFAULT '1' COMMENT 'ссылка на автора',
	`tagNames` VARCHAR(300) NULL DEFAULT NULL,
	`create_type` ENUM('Экспортировано','Создано') NOT NULL DEFAULT 'Создано' COMMENT 'Тип создания',
	`create_time` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Время создания записи',
	`update_date` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Время последнего обновления записи',
	`delete_time` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Время удаления записи',
	PRIMARY KEY (`id`),
	INDEX `idx_objects` (`user_id`),
	INDEX `idx_objects_1` (`create_type`),
	CONSTRAINT `fk_objects_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE
)
COMMENT='Список обьектов'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3;


Таблица атребутов
CREATE TABLE `object_fields` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(20) NOT NULL COMMENT 'Название атребута slug',
	`title` VARCHAR(100) NOT NULL COMMENT 'Название атребута',
	PRIMARY KEY (`id`),
	UNIQUE INDEX `idx_object_fields` (`name`)
)
COMMENT='атребуты обьекта'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=19;


Таблица значений атрибутов
CREATE TABLE `object_field_values` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`object_attr_id` INT(11) NOT NULL COMMENT 'ссылка на атрибут',
	`object_id` INT(11) NOT NULL COMMENT 'Ссылка на обьект',
	`value` VARCHAR(200) NULL DEFAULT NULL COMMENT 'значение',
	PRIMARY KEY (`id`),
	INDEX `idx_object_attr_value` (`object_attr_id`),
	INDEX `idx_object_attr_value_0` (`object_id`),
	CONSTRAINT `fk_object_attr_value` FOREIGN KEY (`object_attr_id`) REFERENCES `object_fields` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE,
	CONSTRAINT `fk_object_attr_value_objects` FOREIGN KEY (`object_id`) REFERENCES `objects` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE
)
COMMENT='Значение атребута'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=5;


Требуется сделать вывод в GridView::widget с возможностью поиска по полям атрибута.
Не могу понять как это реализовать...
  • Вопрос задан
  • 1286 просмотров
Решения вопроса 1
Inviseble_Demon
@Inviseble_Demon Автор вопроса
PHP 15+ лет... к сожалению ^_^
padlyuck Успокоил что это как минимум близко к правде. Итоговое рабочее решение (Но оно мне не нравится ^_^ )

attr_ - отсебятина дабы потом знать что это данные из связки с атрибутами.
После attr_ указываем имя атрибута из таблицы object_fields
getAttr - мой геттер тут ничего интересного все банально.


В views указываем
echo GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $dataFilter,
        'columns' => [
           .....
            [
                'attribute' => 'attr_rooms',
                'value' => function ($model) {
                    return $model->getAttr("rooms")->value;
                }
            ],
           .....
        ],
    ]); ?>


Далее все относится к модели

Объявляем свойство attr_rooms
class Objects extends \yii\db\ActiveRecord
{
...
    public $attr_rooms;
...


Так же добавляем правило
....
 public function rules()
    {
        return [
                ....
            [['attr_rooms'], 'safe'],
                ....
        ];
    }
....


Чуть не забыл - указываем связь многие ко многим.

public function getObjectFields()
    {
        return $this->hasMany(ObjectFields::className(), ['id' => 'object_attr_id'])
            ->viaTable(ObjectFieldValues::tableName(), ['object_id' => 'id']);
    }


Ну и сам поиск (фильтр)
public function adminFiltr($params)
    {
        $query = Objects::find()->joinWith('objectFields');

        $dataProvider = new ActiveDataProvider([
            'query' => $query,
        ]);

        if ($this->load($params))
            // регистрируем поиск по параметрам если они переданы, не пустые и начинаются с "attr_"
            // исключаем attr_ и используем название как название нашего атрибута из object_fields
            foreach ($params[$this->formName()] as $paramName => $paramValue) {
                if (!empty($paramValue) and substr($paramName, 0, 5) == 'attr_') {
                    $paramName = substr($paramName, -5);
                    $query->andFilterWhere([
                        'object_field_values.value' => $paramValue,
                        'object_fields.name' => $paramName,
                    ]);
                }
            }

        return $dataProvider;
    }


Все это работает - НО реализация меня не устраивает - переделаю - отпишусь (если не забуду).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Ваш ответ на вопрос

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

Похожие вопросы