Doctrine: Ein Tagging-Konzept

Das Ziel einer jeden Datenverwaltung sollte es sein, dem Nutzer eine schnelle und sichere Methode zu bieten, auf den zur Verfügung gestellten Daten zu suchen und zu finden. Kann der Nutzer dabei selbst markieren und definieren, was er sucht und findet, nennt man das Kategorisierung oder Tagging. Ein Tag ist dabei nicht mehr, als ein einfacher Name, der einem Objekt zugeordnet wird. Die Website kann somit nicht nur nach den Inhalten der Datenbank, sondern auch nach zutreffenden Tags des Nutzers suchen. Hier ein kleines Tagging-Konzept, um Doctrine die Markierung von Objekten beizubringen.

Eine Superklasse für Entitäten

Kern der Überlegung ist eine Superklasse, von der jede „taggable“ Entity erben kann. Wir nutzen also eine Entität mit einigen Attributen, die uns gleichzeitig als Interface für die Navigation über Tags dient.

/**
 * @ORM\Table(name="taggable")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="child_class_type", type="string")
 * @ORM\DiscriminatorMap({
 *     "group_entity" = "GroupEntity",
 * })
 */
class TaggableEntity
{
    /**
     * @var int
     *
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\Id()
     */
    protected $id;

    /**
     * @var Collection
     *
     * @ORM\ManyToMany(targetEntity="App\Entity\TagEntity", inversedBy="taggables")
     */
    private $taggables;

    public function getId()
    {
        return $this->id;
    }

    // ...
}

Die Superklasse ist verpflichtet das ID-Attribut in allen anderen Entitäten zu liefern. Der Grund dafür ist die Einheitlich Zählung der „Class Table Inheritance“: Beim @InheritanceType("JOINED") wird nicht mehr jede einzelne Tabelle mit einer ID geführt, sondern es existiert eine globale ID über alle „tagbaren“ Tabellen, die in der neuen Tabelle geführt wird. Die interne Zuordnung der Klassen übernimmt Doctrine mit einer @DiscriminatorColumn(). Diese speichert einen von uns in der @DiscriminatorMap() angegebenen String als Referenz.

Aufbau der „tagbaren“ Entitäten

Da keine individuelle ID mehr existiert, verschwinden die Variable und der Getter für ID aus allen „tagbaren“ Entities:

/**
 * @ORM\Table(name="files")
 */
class FileEntity extends TaggableEntity
{
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="mime_type", type="string", length=255, nullable=false)
     */
    private $mimeType;

    // ...

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    // ...
}

Da die ID aus unserer Superklasse protected ist, ist sie weiterhin als normale Variable verwendbar.

Die Tag-Entität

Diese Entität ist die eigentliche Ressource und verknüpft mit unseren „Taggables“. Sie könnte zum Beispiel so aussehen:

/**
 * @ORM\Table(name="tags")
 */
class TagEntity
{
    /**
     * @var int
     *
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Id
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="tag_name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="color", type="string", length=255, nullable=false)
     */
    private $color;

    /**
     * @var bool
     *
     * @ORM\Column(type="boolean")
     */
    private $private = true;

    /**
     * @var TaggableEntity
     *
     * @ORM\ManyToMany(targetEntity="App\Entity\TaggableEntity", mappedBy="tags")
     * @JoinTable(name="tagRelations")
     */
    private $taggables;

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    // ...
}

Und das war es auch schon! Jetzt können nach Belieben Tags erstellt und den anderen „tagbaren“ Entitäten zugeordnet werden. Jeder Tag hat Referenzen auf „Taggables“ und anders herum. In einer Mapping-Tabelle werden alle Verknüpfungen von Doctrine verwaltet. Das war meine kurze Zusammenfassung zum Thema „Doctrine: Ein Tagging-Konzept“.

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert