Блог

Наши новости, публикации и мысли.
  • 30 Сен 13

  • Yii

Сохранение, редактирование и поиск по связям MANY_MANY в Yii

Дано:

  1. Таблица объектов и таблица городов, имеющие связь MANY_MANY;
  2. Yii Framework v.1.1.14;

Задача: организовать редактирование связей и поиск объектов по массиву id городов, используя стандартные средства фреймворка.

При создании практически любого сайт средней сложности перед программистом встает задача организовать корректную работу приложения со связями вида MANY_MANY — создание, редактирование, удаление, поиск и фильтрация.
Итак, приступим. Сперва объявим связи в моделях в методе relations.

Object:

City:

Добавим поле, содержащее массив городов для данного объекта:

Теперь нужно организовать корректное создание и редактирование объекта. Воспользуемся Gii для генерации CRUD операций.

Выводим список городов в форме:

Здесь всё просто — отрисовали селект с атрибутом multiple для множественного выбора и на вход ему дали сгенерированный массив списка городов. Могли воспользоваться также списком чекбоксов например, разницы нет.

Инструмент во view добавили, но теперь нужно корректно сохранить связи. Крайне рекомендую воспользоваться CAdvancedArBehavior при работе со связью MANY_MANY, который возьмет на себя всю работу по редактированию связей, подробнее можете прочитать на странице расширения. Достаточно будет указать:

и мы получим обновленную таблицу связей «object-city». Осталось только корректно подставить выбранные Id из формы — отредактируем методы редактирования и сохранения объектов в контроллере, добавив такие строки:

Не забываем о корректной инициализации формы редактирования. Для этого нам необходимо составить поле cityIds после нахождения объекта в базе. Воспользуемся стандартным обработчиком afterFind:

Вот и всё, мы настроили корректное создание и редактирование связи MANY_MANY. Как же теперь использовать эту связь в фильтре?

Всё просто! Страницу списка сгенерируем через Gii и отредактируем actionIndex в контроллере Object:

Как вы догадались, вся магия происходит на строчке

Здесь можно добавить любое сравнение, выражение используется в итоге в WHERE при выборке из базы. Например сравниваем строки, чтобы искать по названию города:

Особое внимание стоит уделить строке:

Мы не зря её добавили, это поможет нам избежать в дальнейшем проблем с выводом списка всех городов к каждому объекту в таблице, например. Но тут конечно зависит от задачи. Кейсов много, города можно искать и OR, и AND. Всё зависит от вашей фантазии.

Вот и всё, теперь осталось передать $model и $dataProvider в стандартный виджет CGridView и добавить селект cityIds в форму поиска аналогично форме создания объекта.

Бонусом к статье рассмотрим проблему вывода сложных составных html столбцов в CGridView. Одним из вариантов является использование дополнительных методов в модели или контроллере:

Остается только определить метод renderGridColumn, в котором мы можем сформировать любой html, который нам нужен в верстке:

где $data — модель объекта, а $row — номер строки в таблице.

Последние записи

  • При использовании замечательной библиотеки AngularUI для AngularJS может возникнуть проблема со стандартной директивой Typeahead из набора для Bootstrap. Дизайнер UI/UX может потребовать отображать список по фокусу в...
    24 марта 2014
  • После завершения создания сайта встает вопрос об оптимизации загрузки кода. Минификация javascript файлов позволяет уменьшить их размер путем удаления лишних символов, при этом обычно используют обфускацию, т.е....
    04 февраля 2014
  • Создать сайт для предприятия малого бизнеса не сложно. Трудности начнутся, когда вы захотите привлечь на свой новый сайт трафик. Да и качество самого трафика нужно разделять, ведь...
    03 ноября 2013
  • Специфика наполнения сайта контентом обсуждалась неоднократно, и существует множество мнений по поводу того, кто должен писать для веба, и может ли этим заниматься непосредственно сам заказчик. И...
    10 июля 2013