Wenn es ein Thema bzgl. Extbase gibt, dann wohl das Thema um versteckte Datensätze. Gebt bei Google mal „extbase versteckte datensätze“ ein und Ihr erhaltet über 6000 Ergebnisse. Lösung Nummer 1: setEnableFieldsToBeIgnored.
setEnableFieldsToBeIgnored ist eine schöne Lösung, aber diese Lösung hat immer den Nachteil, dass wir auf die in Extbase integrierte Validierung verzichten müssen, die durch den Aufruf von z.B. showAction(Tx_MyExt_Domain_Model_Car $car) automatisch ausgeführt wird.
Schauen wir uns mal an, wie Extbase meinen Parameter $car mit Inhalt befüllt:
public function getObjectByIdentifier($identifier, $className) { if ($this->session->hasIdentifier($identifier, $className)) { return $this->session->getObjectByIdentifier($identifier, $className); } else { $query = $this->persistenceManager->createQueryForType($className); $query->getQuerySettings()->setRespectStoragePage(FALSE); $query->getQuerySettings()->setRespectSysLanguage(FALSE); return $query->matching($query->equals('uid', $identifier))->execute()->getFirst(); } } |
Extbase prüft, ob $car bereits in $this->session registriert wurde. Da $this->session jedoch mit jedem Request wieder geleert wird, dürfte diese Abfrage wohl ins Leere gehen und der Datensatz muss aus der Datenbank neu geholt werden und zwar mit einer unveränderbaren Query seitens Extbase. Das wird wohl auch der Grund sein, warum bei diesem Thema immer wieder Frust hochkommt.
Meine Lösung basiert ebenfalls auf setEnableFieldsToBeIgnored, aber mein Ansatz ist ein völlig anderer. Schauen wir uns meine initializeShowAction() an:
public function initializeShowAction() { $this->registerCarFromRequest('car'); } |
Die Methode registerCarFromRegister() ruft nun eine Methode auf, die sowohl bei anzeigenden Views als auch bei editierende Views funktioniert:
/** * @var Tx_Extbase_Persistence_Session * @inject */ protected $session; protected function registerCarFromRequest($argumentName) { $argument = $this->request->getArgument($argumentName); if (is_array($argument)) { $car = $this->carRepository->findHiddenEntryByUid($argument['__identity']); } else { $car = $this->carRepository->findHiddenEntryByUid($argument); } $this->session->registerObject($car, $car->getUid()); } |
In findByHiddenEntryByUid() arbeite ich wieder wie alle von Euch mit setEnableFieldsToBeIgnored:
public function findHiddenEntryByUid($carUid) { $query = $this->createQuery(); $query->getQuerySettings()->setIgnoreEnableFields(TRUE); $query->getQuerySettings()->setEnableFieldsToBeIgnored(array('disabled')); return $query->matching($query->equals('uid', (int)$carUid))->execute()->getFirst(); } |
Das Geheimnis liegt in dieser Zeile:
$this->session->registerObject($car, $car->getUid()); |
Ich kümmere mich mit Hilfe einer initializeAction selbst darum das gesuchte Objekt über mein Repository zu holen und in den Cache des Backend-Objektes zu implementieren. Wenn nun die showAction aufgerufen wird, findet diese meinen injizierten versteckten Datensatz im Cache und auch die Validierung klappt wieder.
In meinen Augen ist diese Lösung kein Overhead, da die Datenbank bei dieser Lösung kein zweites mal abgefragt werden muss.