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 实体,例如AccountContact.

属性可以这样实现:

 /**
 * @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;