Поведінка Yii2 Behaviors для збереження пов’язаних даних «багато хто до багатьох» (many to many)

yii2

Там все добре, але мене не влаштовувало: неможливість видалити всі дані з таблиці зв'язку, один запис обов'язково залишається надмірна перевантаженість на користь зайвого на мій погляд прагнення до універсалізації. На смак і колір взагалі. Тому я ризикнув написати свій варіантBehaviors Yii2 many to many.

Отже, що нам дано. Є три таблиці:post,tag таpost_has_tag, для них згенеруємо три моделі Post, Tag та PostHasTag, таблиці наприклад такі:

Код моделей наводити не буду, думаю, що генерація моделей за допомогою Gii не має складності. Остання таблиця є таблицею зв'язку між постами і тегами, і вона має лише два поля:post_id іtag_id, з назв полів зрозуміло що має зберігатися. Ось з цією таблицею ми і працюватимемо, поведінка повинна вміти віддавати потрібні дані з цієї таблиці, а також зберігати і при необхідності видаляти їх. Так, і в поведінку як параметри потрібно передавати ім'я зв'язку та ім'я атрибуту моделі.

Що б хотілося: насамперед це простота використання, ну і щоб усе зберігалося, оновлювалося, видалялося, транзакції щоб були, ось власне і все. Так, і мова тут піде саме про тип зв'язку «many to many» через таблицю зв'язку, в якій тільки два стовпці - значення первинних ключів зв'язаних таблиць. Поведінки для роботи зі зв'язками один до одного і до багатьох ми напишемо наступного разу.

Перше що потрібно зробити, це в моделі Post позначити зв'язок багато до багатьох через таблицю зв'язкуpost_has_tag, згідно з документацією Yii2 це робиться таким чином:

Далі необхідно в тій самій моделі Postоголосити поведінку, де tags - це ім'я вищезазначеного зв'язку, а tag_list - ім'я неіснуючого поки атрибута моделі, як він у моделі потім з'явиться буде розказано трохи нижче, підключення дуже просте:

Ну і щоб закінчити з моделлю, до правил валідації додамо safe - атрибутtag_list :

Підготовчі заходи для моделі завершено, залишилося підготувати виставу. Для маніпуляцій з тегами, як і з іншими сутностями, з якими власник зв'язку співвідноситься як один до багатьох абобагато до багатьох, зручно використовувати JQUERY плагін Chosen. Для інтеграції цього плагіна з Yii2 є кілька вже готових рішень, одне з яких ми підключимо в нашому відображенні.

  • tag_list - ім'я атрибуту моделі
  • items - масив тегів, відсортованих на ім'я, і ​​за допомогою методу хелпера ArrayHelper::map приведений до виду ключ (id) - значення (title):

Підготовчі роботи закінчені, настав час приступати до розробки самогоПоведіння. Для початку оголосимо дві властивості:

Далі створимо методevents() і призначимо у ньому обробники подій. У нашому випадку обробник подій буде один -changeRelations.

Магічний метод __get() повертатиме масив айдишників тегів, що належать відповідній посаді:

Магічний метод __set() встановлює приватну властивість $this->_values:

Ну і останній метод у нашій поведінці, який зберігає та видаляє дані із пов'язаної моделі. Метод документований.

На завершення повний код нашої поведінки, який для прикладу можна помістити в папку components\behaviors поточної програми:

Підсумовуючи вищенаписане, можна сказати, що ми отримали поведінку відповідно до наших вимог. Просте у використанні та виконуючевсе, що було задумано :).