Связь «Многие ко многим» (Many to many)
Связь «Многие ко многим» позволяет реализовать такой функционал, как теги.
Для таблиц «posts» и «tags» надо создать таблицу posts_tags, с полями «post_id» и «tag_id». Затем в модели надо добавить метод $this->belongsToMany()
, внутри которого указать таблицу с тегами.
# src/Model/Table/PostsTable.php class PostsTable extends Table { public function initialize(array $config): void { // … $this->belongsToMany('Tags'); } }
Теперь когда надо выбрать статью вместе с тегами, надо добавить параметр contain
.
$post = $this->Posts->get($id, [ 'contain' => 'Tags' ]); // пример вывода тегов foreach ($post->tags as $tag) { echo $this->Html->link($tag->name, ['controller' => 'Tags', 'action' => 'view', $tag->id]); }
Форма для выборки тегов
По умолчанию CakePHP определяет поле «tags._ids» как список для выбора тегов. Добавить теги в данный список можно через свойство options
.
# контроллер $tags = $this->Posts->Tags->find('list'); $this->set(compact('tags')); # шаблон echo $this->Form->control('tags._ids', ['options' => $tags]);
Добавить или изменить тег
Добавить теги можно через следующий код:
$post = $this->Posts->get($id); $data = [ 'title' => 'Имя страницы', 'body' => 'Контент', // добавление тегов 'tags' => [ ['name' => 'php'], ['name' => 'cakephp'], ], ]; $post = $this->Posts->patchEntity($post, $data); $this->Posts->save($post);
Код выше всегда добавляет тег (даже если данный тег уже есть).
Указать ИД тегов можно через следующий код:
$post = $this->Posts->get($id); $data = [ 'title' => 'Имя страницы', 'body' => 'Контент', // указать ИД тегов 'tags' => [ '_ids' => [2,5], ], ]; $post = $this->Posts->patchEntity($post, $data); $this->Posts->save($post);
Вывести страницы по указанному тегу
Сначала в модели тегов надо добавить метод belongsToMany()
, внутри которого указать таблицу со страницами.
# src/Model/Table/TagsTable.php class TagsTable extends Table { public function initialize(array $config): void { // … $this->belongsToMany('Posts'); } }
Теперь когда надо выбрать тег вместе с его страницами, надо добавить параметр contain
.
$tag = $this->Tags->get($id, [ 'contain' => 'Posts' ]); // пример вывода постов foreach ($tag->posts as $post) { echo $this->Html->link($post->title, ['controller' => 'Posts', 'action' => 'view', $post->id]); }
Поддержать автора