Answer the question
In order to leave comments, you need to log in
How to properly implement tags in Symfony?
Good afternoon!
I'm trying to solve, in general, a standard task - to create an article with tags. TK is the following:
class Article
{
protected $tags;
public function __construct()
{
$this->tags = new ArrayCollection();
}
public function tags(): Collection
{
return $this->tags;
}
public function addTag(Tag $tag): self
{
if($this->hasTag($tag) == false) {
$this->tags->add($tag);
}
return $this;
}
public function removeTag(Tag $tag): self
{
if($this->hasTag($tag)) {
$this->tags->removeElement($tag);
}
return $this;
}
public function hasTag(Tag $tag): bool
{
return $this->tags->contains($tag);
}
}
class Tag
{
protected $tagged;
public function __construct()
{
$this->tagged = new ArrayCollection();
}
public function tagged(): Collection
{
return $this->tagged;
}
public function addTagged(Article $tagged): self
{
if($this->hasTagged($tagged) == false) {
$this->tagged->add($tagged);
$tagged->addTag($this);
}
return $this;
}
public function removeTagged(Article $tagged): self
{
if($this->hasTagged($tagged)) {
$this->tagged->removeElement($tagged);
$tagged->removeTag($this);
}
return $this;
}
public function hasTagged(Article $tagged): bool
{
return $this->tagged->contains($tagged);
}
}
final class Tagifier
{
private $tagRepository;
public function __construct(TagRepository $tagRepository)
{
$this->tagRepository = $tagRepository;
}
public function tagify(Article $tagged, string ...$tags)
{
foreach ($tagged->tags() as $tag) {
$tag->removeTagged($tagged);
}
$tagged->tags()->clear();
foreach($tags as $tagName) {
$tag = $this->tagRepository->getByName($tagName);
if(is_null($tag)) {
$tag = new Tag(/* конструимрование из $tagName */);
}
$tagged->addTag($tag);
}
}
}
$article = new Article();
$tagifier = new Tagifier(...);
$tagifier->tagify($article, 'first tag', 'second tag');
$articleRepo->save($article);
<entity name="Article" table="articles">
<!-- ... -->
<many-to-many field="tags" target-entity="Tag" inversed-by="tagged">
<cascade>
<cascade-persist/>
</cascade>
<join-table name="article_tags">
<join-columns>
<join-column name="article_id" on-delete="CASCADE" referenced-column-name="id"/>
</join-columns>
<inverse-join-columns>
<join-column name="tag_id" on-delete="CASCADE" referenced-column-name="id"/>
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
<entity name="Tag" table="tags">
<!-- ... -->
<many-to-many field="tagged" mapped-by="tags" target-entity="Article"/>
</entity>
Answer the question
In order to leave comments, you need to log in
items 3 and 4 are implemented quite simply through lifecycle events in Doctrine. Just hang a handler on preRemove , check the entity type in it and, if it is something suitable (an article or a tag), then check the links of the entity being removed and clean it up if necessary.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question