Связь «Многие ко многим» (Many to many)
15-08-2018
Создание таблиц
Сначала надо создать таблицы 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(), то для поста добавится тотже тег.
ТЕГи: yii2

