如何将标签存储到自定义实体?
How to store tags to custom entity?
我将自定义实体和标签字段定义为:
/**
* @ORM\ManyToMany(targetEntity="Sulu\Bundle\TagBundle\Tag\TagInterface")
* @ORM\JoinTable(name="venue_tags",
* joinColumns={@ORM\JoinColumn(name="venue_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="idTags", referencedColumnName="id")}
* )
*/
private $tags;
然后我有 setter(实际上是加法器),如下所示:
public function addTag(TagInterface $tag)
{
$this->tags[] = $tag;
return $this;
}
字段已添加到表单详细信息中 XML 如:
<property name="tags" type="tag_selection">
<meta>
<title lang="de">Tags</title>
<title lang="en">Tags</title>
</meta>
<tag name="sulu.search.field" type="tags"/>
</property>
在我的管理控制器中 class 我有映射方法:
protected function mapDataToEntity(array $data, Venue $entity): void
{
....
foreach ($data['tags'] as $tag) {
$entity->addTag($tag);
}
....
然而,由于 $data['tags']
我在这里收到字符串数组,而我的 addTag()
需要 TagInterface
对象的实例。我如何从我拥有的字符串创建该对象,通常这是存储标签的正确方法。
更新:
正如@Johannes 建议添加的字段:
/**
* @var TagManagerInterface
*/
private $tagManager;
和构造函数如:
public function __construct(
ViewHandlerInterface $viewHandler,
...
TagManagerInterface $tagManager
) {
$this->viewHandler = $viewHandler;
...
$this->tagManager = $tagManager;
parent::__construct($viewHandler);
}
然后尝试添加这样的标签:
$tagEntities = $this->tagManager->resolveTagNames($data['tags']);
foreach ($tagEntities as $tagEntity) {
$entity->addTag($tagEntity);
}
但是我得到错误:
传递给 App\Entity\Venue::addTag() 的参数 1 必须实现接口 Sulu\Bundle\TagBundle\Tag\TagInterface,给定的 int,在 /var/www/html/src/Controller/Admin/VenueController 中调用。php 第 147 行
我做错了什么?就像我得到标签 ID 一样?我应该以某种方式加载标签吗?
更新二:
添加 findById()
保存标签后有效。但是,现在我又发现了2个问题:
即使关系在保存标签后保存在数据库中也很好,标签字段不再显示。此外,如果我转到概览页面并返回编辑实体 selected(已保存)标签不会重新填充。我还需要添加什么,以便实际使用数据库中保存的标签?
如果我拳头select“Tag1”然后点击“保存”就保存好了。但是,如果我再次编辑实体并再次 select "Tag1" Sulu 尝试使用相同的键创建新行,我会收到错误消息:“SQLSTATE[23000]:违反完整性约束: 1062 密钥 'venue_tags.PRIMARY' 的重复条目“4-1”。我想应该先删除以前保存的密钥,但如何以及在哪里才是最佳方式?
您可以使用 TagManager 服务(id:sulu_tag.tag_manager
或 Sulu\Bundle\TagBundle\Tag\TagManagerInterface
):
$tagIds = $tagManager->resolveTagNames($data['tags']);
foreach ($tagIds as $tagId) {
$entity->addTag($tagManager->findById($tagId));
}
将以下代码添加到您的 class 应该可以解决您的第一个问题
/**
* @Serializer\VirtualProperty
* @Serializer\SerializedName("tags")
*/
public function getTagNameArray()
{
$tags = [];
foreach ($this->getTags() as $tag) {
$tags[] = $tag->getName();
}
return $tags;
}
要修复第二个问题,您必须让 addTag 方法知道您不能与同一标签建立多个关系(检查该标签是否已存在于那里的集合中)。
作为记录,我向我的实体添加了新方法:
public function removeAllTags()
{
foreach ($this->getTags() as $tag) {
$this->removeTag($tag);
}
}
我在添加新标签之前从 mapDataToEntity() 调用:
$tagEntities = $this->tagManager->resolveTagNames($data['tags']);
$entity->removeAllTags();
foreach ($tagEntities as $tagEntity) {
$entity->addTag($this->tagManager->findById($tagEntity));
}
这不仅解决了双键问题,还解决了标签删除的潜在问题。
我将自定义实体和标签字段定义为:
/**
* @ORM\ManyToMany(targetEntity="Sulu\Bundle\TagBundle\Tag\TagInterface")
* @ORM\JoinTable(name="venue_tags",
* joinColumns={@ORM\JoinColumn(name="venue_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="idTags", referencedColumnName="id")}
* )
*/
private $tags;
然后我有 setter(实际上是加法器),如下所示:
public function addTag(TagInterface $tag)
{
$this->tags[] = $tag;
return $this;
}
字段已添加到表单详细信息中 XML 如:
<property name="tags" type="tag_selection">
<meta>
<title lang="de">Tags</title>
<title lang="en">Tags</title>
</meta>
<tag name="sulu.search.field" type="tags"/>
</property>
在我的管理控制器中 class 我有映射方法:
protected function mapDataToEntity(array $data, Venue $entity): void
{
....
foreach ($data['tags'] as $tag) {
$entity->addTag($tag);
}
....
然而,由于 $data['tags']
我在这里收到字符串数组,而我的 addTag()
需要 TagInterface
对象的实例。我如何从我拥有的字符串创建该对象,通常这是存储标签的正确方法。
更新:
正如@Johannes 建议添加的字段:
/**
* @var TagManagerInterface
*/
private $tagManager;
和构造函数如:
public function __construct(
ViewHandlerInterface $viewHandler,
...
TagManagerInterface $tagManager
) {
$this->viewHandler = $viewHandler;
...
$this->tagManager = $tagManager;
parent::__construct($viewHandler);
}
然后尝试添加这样的标签:
$tagEntities = $this->tagManager->resolveTagNames($data['tags']);
foreach ($tagEntities as $tagEntity) {
$entity->addTag($tagEntity);
}
但是我得到错误:
传递给 App\Entity\Venue::addTag() 的参数 1 必须实现接口 Sulu\Bundle\TagBundle\Tag\TagInterface,给定的 int,在 /var/www/html/src/Controller/Admin/VenueController 中调用。php 第 147 行
我做错了什么?就像我得到标签 ID 一样?我应该以某种方式加载标签吗?
更新二:
添加 findById()
保存标签后有效。但是,现在我又发现了2个问题:
即使关系在保存标签后保存在数据库中也很好,标签字段不再显示。此外,如果我转到概览页面并返回编辑实体 selected(已保存)标签不会重新填充。我还需要添加什么,以便实际使用数据库中保存的标签?
如果我拳头select“Tag1”然后点击“保存”就保存好了。但是,如果我再次编辑实体并再次 select "Tag1" Sulu 尝试使用相同的键创建新行,我会收到错误消息:“SQLSTATE[23000]:违反完整性约束: 1062 密钥 'venue_tags.PRIMARY' 的重复条目“4-1”。我想应该先删除以前保存的密钥,但如何以及在哪里才是最佳方式?
您可以使用 TagManager 服务(id:sulu_tag.tag_manager
或 Sulu\Bundle\TagBundle\Tag\TagManagerInterface
):
$tagIds = $tagManager->resolveTagNames($data['tags']);
foreach ($tagIds as $tagId) {
$entity->addTag($tagManager->findById($tagId));
}
将以下代码添加到您的 class 应该可以解决您的第一个问题
/**
* @Serializer\VirtualProperty
* @Serializer\SerializedName("tags")
*/
public function getTagNameArray()
{
$tags = [];
foreach ($this->getTags() as $tag) {
$tags[] = $tag->getName();
}
return $tags;
}
要修复第二个问题,您必须让 addTag 方法知道您不能与同一标签建立多个关系(检查该标签是否已存在于那里的集合中)。
作为记录,我向我的实体添加了新方法:
public function removeAllTags()
{
foreach ($this->getTags() as $tag) {
$this->removeTag($tag);
}
}
我在添加新标签之前从 mapDataToEntity() 调用:
$tagEntities = $this->tagManager->resolveTagNames($data['tags']);
$entity->removeAllTags();
foreach ($tagEntities as $tagEntity) {
$entity->addTag($this->tagManager->findById($tagEntity));
}
这不仅解决了双键问题,还解决了标签删除的潜在问题。