Sulu:将标签字段添加到自定义实体
Sulu: adding tags field to custom entity
如何给自定义实体添加tags字段?它应该是什么样的(学说)领域类型?我找不到任何文档或示例。
更新:
我按照@Prokyon 的说明将字段添加到我的自定义实体,但它看起来不像这样:
<?php
declare(strict_types=1);
namespace App\Entity;
use App\Repository\VenueRepository;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use JMS\Serializer\Annotation as Serializer;
use Doctrine\Common\Collections\ArrayCollection;
use Sulu\Bundle\MediaBundle\Entity\MediaInterface;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\Groups;
use Sulu\Bundle\TagBundle\Tag\TagInterface;
use JMS\Serializer\Annotation\Type;
/**
* @ORM\Entity(repositoryClass=VenueRepository::class)
*/
class Venue
{
const RESOURCE_KEY = 'venue';
const SECURITY_CONTEXT = 'sulu.matchcentre.venues';
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private ?string $locationName;
/**
* @ORM\Column(type="string", length=255)
*/
private ?string $shortName;
/**
* @var MediaInterface|null
*
* @ORM\ManyToOne(targetEntity="Sulu\Bundle\MediaBundle\Entity\MediaInterface")
*
* @Serializer\Exclude
*/
private $image = null;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private ?string $googleMapsLink;
/**
* @ORM\Column(type="smallint")
*/
private ?int $country;
/**
* @var Collection<int, TagInterface>
* @Accessor(getter="getTagNameArray")
* @Groups({"fullContact"})
* @Type("array")
*/
protected $tags;
/**
* @var Collection<string, VenueTranslation>
*
* @ORM\OneToMany(targetEntity="App\Entity\VenueTranslation", mappedBy="venue", cascade={"ALL"}, indexBy="locale")
*
* @Serializer\Exclude
*/
private $translations;
/**
* @var string
*/
private $locale;
public function __construct()
{
$this->translations = new ArrayCollection();
$this->tags = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getLocationName(): ?string
{
return $this->locationName;
}
public function setLocationName(?string $locationName): self
{
$this->locationName = $locationName;
return $this;
}
public function getShortName(): ?string
{
return $this->shortName;
}
public function setShortName(?string $shortName): self
{
$this->shortName = $shortName;
return $this;
}
/**
* @Serializer\VirtualProperty(name="description")
*/
public function getDescription(): ?string
{
$translation = $this->getTranslation($this->locale);
if (!$translation) {
return null;
}
return $translation->getDescription();
}
public function setDescription(?string $description): self
{
$translation = $this->getTranslation($this->locale);
if (!$translation) {
$translation = $this->createTranslation($this->locale);
}
$translation->setDescription($description);
return $this;
}
public function getImage(): ?MediaInterface
{
return $this->image;
}
/**
* @return array<string, mixed>|null
*
* @Serializer\VirtualProperty
* @Serializer\SerializedName("image")
*/
public function getImageData(): ?array
{
if (!$this->image) {
return null;
}
return [
'id' => $this->image->getId(),
];
}
public function setImage(?MediaInterface $image): self
{
$this->image = $image;
return $this;
}
public function getGoogleMapsLink(): ?string
{
return $this->googleMapsLink;
}
public function setGoogleMapsLink(?string $googleMapsLink): self
{
$this->googleMapsLink = $googleMapsLink;
return $this;
}
public function getCountry(): ?int
{
return $this->country;
}
public function setCountry(?int $country): self
{
$this->country = $country;
return $this;
}
public function addTag(TagInterface $tag)
{
$this->tags[] = $tag;
return $this;
}
public function removeTag(TagInterface $tag)
{
$this->tags->removeElement($tag);
}
public function getTags()
{
return $this->tags;
}
public function getTagNameArray()
{
$tags = [];
foreach ($this->getTags() as $tag) {
$tags[] = $tag->getName();
}
return $tags;
}
public function getLocale(): string
{
return $this->locale;
}
public function setLocale(string $locale): self
{
$this->locale = $locale;
return $this;
}
/**
* @return VenueTranslation[]
*/
public function getTranslations(): array
{
return $this->translations->toArray();
}
protected function getTranslation(string $locale): ?VenueTranslation
{
if (!$this->translations->containsKey($locale)) {
return null;
}
return $this->translations->get($locale);
}
protected function createTranslation(string $locale): VenueTranslation
{
$translation = new VenueTranslation($this, $locale);
$this->translations->set($locale, $translation);
return $translation;
}
}
但问题是当我尝试 运行:
bin/console doctrine:migrations:diff
我收到回复:“在您的映射信息中未检测到任何更改。”
最好的方法是查看带有标签的现有 sulu 实体,例如Account
或 Contact
.
属性可以这样实现:
/**
* @var Collection<int, TagInterface>
*/
protected $tags;
有关详细信息,请参阅 Conctact.php。
学说映射可以这样配置:
<many-to-many field="tags" target-entity="Sulu\Bundle\TagBundle\Tag\TagInterface">
<join-table name="co_contact_tags">
<join-columns>
<join-column name="idContacts" referenced-column-name="id"/>
</join-columns>
<inverse-join-columns>
<join-column name="idTags" referenced-column-name="id"/>
</inverse-join-columns>
</join-table>
</many-to-many>
有关实体的完整学说配置,请参阅Contact.orm.xml。
此外,您可以在此处阅读更多关于学说实体配置的信息doctrine mapping
更新:
您添加到 $tag
属性 的注释仅用于序列化。你真的不需要它们。但是您完全缺少映射的学说注释。
这是正确的条令注释的示例,但您仍然需要为您的实体调整表和映射列。查看上面的link关于学说映射的更多说明。
/**
* Many Users have Many Groups.
* @ManyToMany(targetEntity="Sulu\Bundle\TagBundle\Tag\TagInterface")
* @JoinTable(name="venue_tags",
* joinColumns={@JoinColumn(name="venue_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="idTags", referencedColumnName="id")}
* )
*/
private $tags;
如何给自定义实体添加tags字段?它应该是什么样的(学说)领域类型?我找不到任何文档或示例。
更新:
我按照@Prokyon 的说明将字段添加到我的自定义实体,但它看起来不像这样:
<?php
declare(strict_types=1);
namespace App\Entity;
use App\Repository\VenueRepository;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use JMS\Serializer\Annotation as Serializer;
use Doctrine\Common\Collections\ArrayCollection;
use Sulu\Bundle\MediaBundle\Entity\MediaInterface;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\Groups;
use Sulu\Bundle\TagBundle\Tag\TagInterface;
use JMS\Serializer\Annotation\Type;
/**
* @ORM\Entity(repositoryClass=VenueRepository::class)
*/
class Venue
{
const RESOURCE_KEY = 'venue';
const SECURITY_CONTEXT = 'sulu.matchcentre.venues';
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private ?string $locationName;
/**
* @ORM\Column(type="string", length=255)
*/
private ?string $shortName;
/**
* @var MediaInterface|null
*
* @ORM\ManyToOne(targetEntity="Sulu\Bundle\MediaBundle\Entity\MediaInterface")
*
* @Serializer\Exclude
*/
private $image = null;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private ?string $googleMapsLink;
/**
* @ORM\Column(type="smallint")
*/
private ?int $country;
/**
* @var Collection<int, TagInterface>
* @Accessor(getter="getTagNameArray")
* @Groups({"fullContact"})
* @Type("array")
*/
protected $tags;
/**
* @var Collection<string, VenueTranslation>
*
* @ORM\OneToMany(targetEntity="App\Entity\VenueTranslation", mappedBy="venue", cascade={"ALL"}, indexBy="locale")
*
* @Serializer\Exclude
*/
private $translations;
/**
* @var string
*/
private $locale;
public function __construct()
{
$this->translations = new ArrayCollection();
$this->tags = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getLocationName(): ?string
{
return $this->locationName;
}
public function setLocationName(?string $locationName): self
{
$this->locationName = $locationName;
return $this;
}
public function getShortName(): ?string
{
return $this->shortName;
}
public function setShortName(?string $shortName): self
{
$this->shortName = $shortName;
return $this;
}
/**
* @Serializer\VirtualProperty(name="description")
*/
public function getDescription(): ?string
{
$translation = $this->getTranslation($this->locale);
if (!$translation) {
return null;
}
return $translation->getDescription();
}
public function setDescription(?string $description): self
{
$translation = $this->getTranslation($this->locale);
if (!$translation) {
$translation = $this->createTranslation($this->locale);
}
$translation->setDescription($description);
return $this;
}
public function getImage(): ?MediaInterface
{
return $this->image;
}
/**
* @return array<string, mixed>|null
*
* @Serializer\VirtualProperty
* @Serializer\SerializedName("image")
*/
public function getImageData(): ?array
{
if (!$this->image) {
return null;
}
return [
'id' => $this->image->getId(),
];
}
public function setImage(?MediaInterface $image): self
{
$this->image = $image;
return $this;
}
public function getGoogleMapsLink(): ?string
{
return $this->googleMapsLink;
}
public function setGoogleMapsLink(?string $googleMapsLink): self
{
$this->googleMapsLink = $googleMapsLink;
return $this;
}
public function getCountry(): ?int
{
return $this->country;
}
public function setCountry(?int $country): self
{
$this->country = $country;
return $this;
}
public function addTag(TagInterface $tag)
{
$this->tags[] = $tag;
return $this;
}
public function removeTag(TagInterface $tag)
{
$this->tags->removeElement($tag);
}
public function getTags()
{
return $this->tags;
}
public function getTagNameArray()
{
$tags = [];
foreach ($this->getTags() as $tag) {
$tags[] = $tag->getName();
}
return $tags;
}
public function getLocale(): string
{
return $this->locale;
}
public function setLocale(string $locale): self
{
$this->locale = $locale;
return $this;
}
/**
* @return VenueTranslation[]
*/
public function getTranslations(): array
{
return $this->translations->toArray();
}
protected function getTranslation(string $locale): ?VenueTranslation
{
if (!$this->translations->containsKey($locale)) {
return null;
}
return $this->translations->get($locale);
}
protected function createTranslation(string $locale): VenueTranslation
{
$translation = new VenueTranslation($this, $locale);
$this->translations->set($locale, $translation);
return $translation;
}
}
但问题是当我尝试 运行:
bin/console doctrine:migrations:diff
我收到回复:“在您的映射信息中未检测到任何更改。”
最好的方法是查看带有标签的现有 sulu 实体,例如Account
或 Contact
.
属性可以这样实现:
/**
* @var Collection<int, TagInterface>
*/
protected $tags;
有关详细信息,请参阅 Conctact.php。
学说映射可以这样配置:
<many-to-many field="tags" target-entity="Sulu\Bundle\TagBundle\Tag\TagInterface">
<join-table name="co_contact_tags">
<join-columns>
<join-column name="idContacts" referenced-column-name="id"/>
</join-columns>
<inverse-join-columns>
<join-column name="idTags" referenced-column-name="id"/>
</inverse-join-columns>
</join-table>
</many-to-many>
有关实体的完整学说配置,请参阅Contact.orm.xml。
此外,您可以在此处阅读更多关于学说实体配置的信息doctrine mapping
更新:
您添加到 $tag
属性 的注释仅用于序列化。你真的不需要它们。但是您完全缺少映射的学说注释。
这是正确的条令注释的示例,但您仍然需要为您的实体调整表和映射列。查看上面的link关于学说映射的更多说明。
/**
* Many Users have Many Groups.
* @ManyToMany(targetEntity="Sulu\Bundle\TagBundle\Tag\TagInterface")
* @JoinTable(name="venue_tags",
* joinColumns={@JoinColumn(name="venue_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="idTags", referencedColumnName="id")}
* )
*/
private $tags;