Teil 2: Systemkategorien in Datensätzen der eigenen Extension verfügbar machen
Leider lassen sich die Kategorien nicht mit dem Extension Builder direkt in die neue Extension integrieren. Stattdessen legt man ein ein Feld als „Verweis“ an, Verbindet diesen Verweis aber nicht mit einem anderen Model. Wenn es möglich sein soll, mehrere Kategorien auszuwählen, nennt man das Feld „categories“.
Modellierung der Beziehung zu den Kategorien im Extbase-Model
Nun bearbeitet man das Model, das kategorisiert werden soll, bei mir lw_pinboard/Classes/Domain/Model/Message.php
In der Regel ist es ja möglich, einem Datensatz mehrere Kategorien zuzuweisen. Und natürlich kann auch eine Kategorie viele Datensätze enthalten. Deshalb handelt es sich um eine m:n Beziehung. Diese lässt sich in Extbase wie folgt modelieren.
Das Feld muss ein ObjectStorage sein:
/** * category * * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\LW\LwPinboard\Domain\Model\Category> */ protected $categories = null;
man darf nicht vergessen, den ObjectStorage im Konstruktor des Models zu initialisieren, denn sonst kommt es zu Fehlermeldungen.
public function __construct() { $this->setCategories(new \TYPO3\CMS\Extbase\Persistence\ObjectStorage); }
Nun müssen neben dem klassischen Getter und Setter auch noch ein Adder und Remover zum Model hinzugefügt werden:
/** * Returns the categories * * @return $categories */ public function getCategories() { return $this->categories; } /** * Sets the category * * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\LW\LwPinboard\Domain\Model\Category> $categories * @return void */ public function setCategories(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $categories) { $this->categories = $categories; } /** * Adds a category * * @param \LW\LwPinboard\Domain\Model\Category $category * @return void */ public function addCategory(\LW\LwPinboard\Domain\Model\Category $category) { $this->categories->attach($category); } /** * Removes a category * * @param \LW\LwPinboard\Domain\Model\Category $category * @return void */ public function removeCategory(\LW\LwPinboard\Domain\Model\Category $category) { $this->categories->detach($category); }
Anpassung des TCA zum Anzeigen und Ändern der Kategorien im Backend
Nun muss noch das TCA der Tabelle des Models Message angepasst werden, in meinem Fall: lw_pinboard/Configuration/TCA/tx_lwpinboard_domain_model_message.php
Das Feld categories wird wie folgt in den columns angepasst:
'categories' => [ 'exclude' => true, 'label' => 'LLL:EXT:lw_pinboard/Resources/Private/Language/locallang_db.xlf:tx_lwpinboard_domain_model_message.category', 'config' => [ 'type' => 'inline', 'foreign_table' => '', 'minitems' => 0, 'maxitems' => 1, 'appearance' => [ 'collapseAll' => 0, 'levelLinksPosition' => 'top', 'showSynchronizationLink' => 1, 'showPossibleLocalizationRecords' => 1, 'showAllLocalizationLink' => 1 ], ], ],
Zusätzlich muss das Feld noch kategorisiert werden. Dazu vor dem return in der selben Datei folgendes aufrufen:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::makeCategorizable( 'LW.' . $_EXTKEY, 'tx_lwpinboard_domain_model_message', 'categories' );
Die Kategorien im eigenen Controller der Extension
Nun kann man z.B. im Controller eine Ansicht mit nur den Nachrichten einer Kategorie konfigurieren: lw_pinboard/Classes/Controller/MessageController.php
/** * action list * * @return void */ public function listAction() { $arguments = $this->request->getArguments(); $category = 0; if($arguments && $arguments['cat']) { $category = intval($arguments['cat']); } if ($category != 0) { $messages = $this->messageRepository->findByCategory($category); } else { $messages = $this->messageRepository->findAll(); } $categoryList = $this->categoryRepository->findAll(); $this->view->assign('messages', $messages); $this->view->assign('categoryList', $categoryList); }
Die Methode findByCategory ist nicht standardmäßig in einem Repository vorhanden, sondern muss noch implementiert werden. Auf keinen Fall darf man die Magic Methode findByCategories nutzen. Diese liefert nämlich die falschen Daten und ggf keine Fehlermeldung und das kommt so: TYPO3 speichert im Feld categories in der Datenbank bei einer m:n Beziehung die ANZAHL der Kategorien. Wenn nun Mein Datensatz zwei Kategorien hat, steht hier also eine 2. Wenn ich nun nach Nachrichten in der Kategorie mit uid 2 suche und die Magic Methode findByCategories nutze, so liefert mir nun Extbase alle Nachrichten zurück, die zu zwei Kategorien zugewiesen wurden.
Methode findByCategory im Repository der Message implementieren
Also editieren wir nun noch das Repository unseres eigenen Datensatzes, hier der Message: lw_pinboard/Classes/Domain/Repository/MessageRepository.php
/** * Finds an object matching the given identifier. * * @param int $categoryid The identifier of the category to find Messages from * @return object The matching object if found, otherwise NULL * @api */ public function findByCategory($categoryid) { $query = $this->createQuery(); $query->matching($query->contains('categories', $categoryid)); return $query->execute(); }