Связь «Многие ко многим» (Many to many)
Создание таблиц
Сначала надо создать таблицы post, tag и post_tag.
yii migrate/create create_posts_table --fields="title:string:notNull,content:text" yii migrate/create create_tag_table --fields="title:strinf:notNull" yii migrate/create_junction_table_for_post_and_tag_tables yii migrate
Также надо создать модели Post и Tag.
# models/Post.php namespace app\models; use Yii; class Post extends \yii\db\ActiveRecord { } # models/Tag.php namespace app\models; use Yii; class Tag extends \yii\db\ActiveRecord { }
Вывод тегов
В файле models/Post.php надо добавить следующий код:
# models/Post.php class Post extends \yii\db\ActiveRecord { public function getTags() { return $this->hasMany(Tag::classname(), ['id' => 'tag_id']) ->viaTable('post_tag', ['post_id' => 'id']); } }
Теперь можно выбирать комментарии:
# controllers/PostController.php class PostController extends Controller { public function actionView() { // выборка тегов поста $post = Post::findOne(1); $tags = $post->tags; } }
Когда идёт обращение к свойству tags
, происходит дополнительный SQL-запрос для выборка комментариев. Такое поведение называется «Lazy load», т.е. данные загружается тогда, когда они нужны.
Но при выборке нескольких страниц, для каждой страницы будет происходить дополнительный запрос в базу данных. Чтобы такого не происходило, рекомендуется использовать метод with()
, который сразу выберет нужные теги при выборки страниц.
# controllers/PostController.php class PostController extends Controller { public function actionIndex() { $posts = Post::find()->with('tags')->all(); foreach ($posts as $post) { // здесь SQL-запросов не будет, т.к. данные загрузились при выборке постов $post->tags; } } }
Добавление тега
Тег добавляется через метод link()
.
$post = Post::findOne(4); $tag = Tag::findOne(1); // добавить тег к посту $post->link('tags', $tag);
Если повторно выполнить метод link()
, то для поста добавится тотже тег.
Поддержать автора