Zum Inhalt springen

Kann ich eigene Formulare im BE-Editor eines Content-Elements einbinden

Erstellt am 21. Juli 2011 · 12 Antworten · letzte Antwort am 25. Juli 2011

Tags: Frage

hurikhan77 ·

Hallo!

Ich würde gern das MVC-Framework nutzen, um in einem Seitenelement eigene Tabellen zu füllen. Mir fehlt allerdings scheinbar komplett der Ansatz und ich bin auch völliger Neuling in Typo3 (das MVC-Konzept habe ich dank Ruby on Rails Vorkenntnissen aber schnell durchschaut). Da ein Bild mehr sagt, als 1000 Worte, hier zunächst ein Screenshot, wovon ich rede:

Typo3 Backend Screenshot

Dort im roten Kasten möchte ich gern ein eigenes Formular einbinden, und zwar nicht bestehend aus Standard-Feldtypen, und auch keine Felder aus tt_content. Das bedeutet, ich müsste eigenen HTML-Code ausgeben. Mein Extbase-Plugin taucht bereits in der Dropdown-Liste auf, wie man sieht. Aber ich bekomme es nicht so konfiguriert, dass ich mir unterhalb Daten einer Fremdtabelle ausgeben lassen kann.

Die besagte Fremdtabelle sollt für ein Content Element 0 oder mehrere Zeilen enthalten, sprich ich bräuchte noch einen Fremdschlüssel in die tt_content Tabelle vermutlich. Alternativ schalte ich gern eine Verknüpfungstabelle dazwischen, aber ich glaube das wäre das selbe in grün.

Zwei Fragen stellen sich also:

* Wie bringe ich der Konfiguration bei, dass im Backend-Editor Felder einer anderen Tabelle als tt_content ausgegeben werden.

* Wie kann ich selbst programmierte Templates bzw. von mir gesteuert Formulare ins Backend rendern?

Eine Alternative über ein eigenständiges Backend-Modul ist eigentlich nicht gangbar, da diese Daten direkt mit dem Seiteneintrag verknüpft sein müssen.

Eydamos ·

Das Zauberwort hier ist Flexform.

Ich würde dir aber empfehlen, dass du erstmal ein Extbase Tutorial abarbeitest, da du anscheinend so ziemlich garnichts darüber weißt wie man eine Extension mit TYPO3 und insbesondere mit Extbase umsetzt.

hurikhan77 ·
Eydamos schrieb

Das Zauberwort hier ist Flexform.

Ja, das hatte ich auch zunächst gehofft - aber am Ende sind das doch nur XML-Dateien, die statische Formularfelder beschreiben. Ich brauche das wesentlich flexibler. Javascript-Code müsste dynamisch neue Formularfelder hinzufügen und alles in einem Rutsch speichern. Ich glaube langsam, dass das Backend dafür nicht geeignet ist oder sehr müssig wird - zumindest im Content Element Editor. Ich werd mir Flexforms trotzdem gleich nochmal genauer anschauen...

Eydamos schrieb

Ich würde dir aber empfehlen, dass du erstmal ein Extbase Tutorial abarbeitest, da du anscheinend so ziemlich garnichts darüber weißt wie man eine Extension mit TYPO3 und insbesondere mit Extbase umsetzt.

Für die TCA-Syntax braucht man ja auch einen Kryptografie-Lehrgang - ansonsten habe ich das Tutorial hier durchgearbeitet (Extbase und Fluid) und mich noch nach anderen umgeschaut. Aber mir scheint so, als seien Tutorials generell auf dem Stand von Typo3 4.3 und nicht 4.5 - und viele, die Extbase angeblich verwenden, bauen teilweise weiterhin gemischt auf pi_base auf, bzw. verwenden ausschließlich tt_content. Das hilft mir alles nichts. Wo finde ich noch sinnvolle Tutorials? Links sind herzlich willkommen.

PS: Wenn es nicht geht, an der markierten Stelle eigens gestaltete Formulare (mit eigenem HTML- und JS-Code, alternativ Ajax zum dyn. erweitern des Formulars) hinzuzufügen, dann möchte ich das nicht mit dem Durcharbeiten von Tutorials rausfinden - das sprengt den Zeitrahmen. Dann müssen wir im Projekt einen anderen Ansatz verfolgen.

oliver_g ·

Hi,

also für solche tiefgreifenden Änderungen müsstest du selbst ein Backend-Modul schreiben. Das geht natürlich mit Extbase oder auch klassisch.

Du solltest das Listen-Modul von Typo3 eher als Low-Level-Modul für die direkte Datensatzbearbeitung auffassen. Spezielle Funktionalität lässt sich da nicht reinpacken, wenn doch, bräuchte man ja auch keine Backend-Module mehr schreiben und Typo3 wäre eine eierlegende Wollmichsau ;-)

Gruß

hurikhan77 ·
oliver_g schrieb

Hi,

also für solche tiefgreifenden Änderungen müsstest du selbst ein Backend-Modul schreiben. Das geht natürlich mit Extbase oder auch klassisch.

Du solltest das Listen-Modul von Typo3 eher als Low-Level-Modul für die direkte Datensatzbearbeitung auffassen. Spezielle Funktionalität lässt sich da nicht reinpacken, wenn doch, bräuchte man ja auch keine Backend-Module mehr schreiben und Typo3 wäre eine eierlegende Wollmichsau ;-)

Gruß

Sehr schön, das ist der Weg, den ich nun gehe. Den Ansatz haben wir bereits umgebaut, ich habe die Extension bereinigt, indem ich ein nicht benötigtes Modell gelöscht habe, das Frontend-Modul entfernt habe und die verbleibenden Dateien und Konfigurationen gelöscht habe.

Laut Konvention sollen die Views dann unter "EXT:.../Resources/Private/Backend/Templates" gesucht werden - das ist laut constants.txt auch so eingerichtet:

module.tx_lltreisen {
	view {
		# cat=module.tx_lltreisen/file; type=string; label=Path to template root (BE)
		templateRootPath = EXT:lltreisen/Resources/Private/Backend/Templates/
		# cat=module.tx_lltreisen/file; type=string; label=Path to template partials (BE)
		partialRootPath = EXT:lltreisen/Resources/Private/Backend/Partials/
		# cat=module.tx_lltreisen/file; type=string; label=Path to template layouts (BE)
		layoutRootPath = EXT:lltreisen/Resources/Private/Backend/Layouts/
	}
	persistence {
		# cat=module.tx_lltreisen//a; type=int+; label=Default storage PID
		storagePid =
	}
}

setup.txt greift darauf zurück:

# Module configuration
module.tx_lltreisen {
	persistence {
		storagePid = {$module.tx_lltreisen.persistence.storagePid}
	}
	view {
		templateRootPath = {$module.tx_lltreisen.view.templateRootPath}
		partialRootPath = {$module.tx_lltreisen.view.partialRootPath}
		layoutRootPath = {$module.tx_lltreisen.view.layoutRootPath}
	}
}

Die Views werden trotzdem nicht an dieser Stelle gesucht, sondern dort, wo Frontend-Templates liegen würden: "EXT:.../Resources/Private/Templates" (es fehlt das Backend-Verzeichnis im Pfad). Wenn ich die Views rüberkopiere, funktioniert es - das kommt mir aber falsch vor.

Die ext_tables.php sieht wie folgt aus:

if (TYPO3_MODE === 'BE') {

	/**
	* Registers a Backend Module
	*/
	Tx_Extbase_Utility_Extension::registerModule(
		$_EXTKEY,
		'web',	 // Make module a submodule of 'web'
		'lltreiseform',	// Submodule key
		'after:layout',						// Position
		array(
			'TravelDetail' => 'list, show, new, create, edit, update, delete',
		),
		array(
			'access' => 'user,group',
			'icon'   => 'EXT:' . $_EXTKEY . '/ext_icon.gif',
			'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_lltreiseform.xml',
		)
	);

}

Die ext_localconf.php ist leer, da war vorher ein registerPlugin-Aufruf, der dürfte m.E. hinfällig sein, da ich ja nun kein Plugin mehr erstelle, sondern ein Modul.

Eine Idee?

hurikhan77 ·

Nachdem ich nochmal die Caches geleert hatte und alle Temp-Dateien entfernt und das Backend neu geladen hatte, funktionierte es mit den Pfaden.

Weiß jemand eine bessere Möglichkeit, die aktuelle Id der Seite im Seitenbaum als StoragePageId zu setzen (also dynamisch, nicht statisch über Typoscript/constants.txt), als so:

/**
 * Initializes the controller before invoking an action method.
 *
 * @return void
 */
protected function initializeAction() {
	$configuration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
	$configuration['persistence']['storagePid'] = sprintf("%s", t3lib_div::_GP('id'));
	$this->configurationManager->setConfiguration($configuration);
}

Hintergrund: Die Datensätze sollen für die jeweilige im Seitenbaum gewählte Seite angelegt werden und auch entsprechend gefiltert angezeigt werden. Eine statische Hinterlegung als Template-Typoscript in der jeweiligen Seite würde sicher auch funktionieren, aber der Kunde fügt Seiten dynamisch hinzu und entfernt sie wieder - wir können vom Kunden nicht erwarten, dort jedesmal ein Typoscript-Setup zu hinterlegen.

oliver_g ·

Ich ignoriere die StoragePID immer und habe dafür bei jedem meiner Objekte eine Eigenschaft PID. Diese setze ich nach Belieben. Der PersistanceLayer schreibt diese auch brav in die Datenbank.

Das ganze Konzept mit der StoragePID ist mir zu unausgegoren. Daher dieser Weg.

Gruß

hurikhan77 ·
oliver_g schrieb

Das ganze Konzept mit der StoragePID ist mir zu unausgegoren. Daher dieser Weg.

Ist auch im Code nicht besonders toll umgesetzt - wenn ich das mal mit den Scopes von Ruby on Rails vergleichen darf. Das Setzen der StoragePID beim Suchen von Datensätzen liegt zwei Ebenen tiefer - geht ja noch, da kann man noch eingreifen. Beim Schreiben von Datensätzen findet das allerdings irgendwo tief im Persistence-Layer statt, nicht mehr im Query-Layer. Das ist somit nicht nur unerreichbar, sondern auch irgendwie unlogisch bzw. schlechtes Design. Dabei könnte es so einfach sein, wenn es einen Mechanismus für den Controller gäbe, die gewünschte StoragePID dynamisch vorzugeben - die aktuelle, verkorkste Implementierung ließe sich damit auch geschickt sauber machen, schließlich ist laut Klassenname der Action-Controller sowieso schon eine Spezialisierung für Typo3.

In Rails hätte ich einfach einen Default-Scope um das Modell erzeugt vom Controller aus, das sind 3 Code-Zeilen - und alles wäre gut gelaufen. Ich vermute, sowas wie Scopes beherrscht Extbase/Flow3 nicht, oder? Ich bin ziemlich tief eingestiegen in den Code, und Queries zum Schreiben und Lesen sind zwei völlig unterschiedliche Code-Pfade, sogar unterschiedliche Ebenen bzw. Hierarchie-Zweige - sprich: Etwas in Richtung Scoping ist mir nicht untergekommen.

Eydamos ·

Das konzept mit den PID's ist nicht unausgegoren, ihr könnt nur nicht damit umgehen und seit zu faul euch damit zu beschäftigen.

Andere Extensions kriegen es schließlich auch hin basierend auf der gerade gewählten Seite Datensätze anzuzeigen und zu speichern.

Sicher gibt es dafür entsprechende Funktionen die muss man nur kennen. Also googelt oder arbeitet euch in den Code ein, aber meckert nicht rum das etwas schlecht ist nur weil ihr nicht damit umgehen könnt.

Just my 2 cents.

hurikhan77 ·
Eydamos schrieb

Das konzept mit den PID's ist nicht unausgegoren, ihr könnt nur nicht damit umgehen und seit zu faul euch damit zu beschäftigen.

Ich bitte um Links, die deine These unterstützen. Oder weißt du es selbst eigentlich nicht genau?

Eydamos schrieb

Andere Extensions kriegen es schließlich auch hin basierend auf der gerade gewählten Seite Datensätze anzuzeigen und zu speichern.

Meine ja nun auch - also warum hier rumstänkern und das Gegenteil behaupten? Der Weg dahin ist nur umständlich und scheinbar - zumindest in Extbase - von den Entwicklern noch nicht ganz fertig programmiert. Ergo: unausgegoren (auch wenn das ursprünglich nicht meine Worte waren, aber es bringt die Sache nun mal auf den Punkt).

Eydamos schrieb

Sicher gibt es dafür entsprechende Funktionen die muss man nur kennen.

Wie gesagt: Links bitte. Denn entweder weißt du es scheinbar, wie es geht und was es für tolle API-Aufrufe gibt, oder aber du stellst nur leere Behauptungen in den Raum und trollst hier nur rum. Google hab ich übrigens intensivst genutzt - Log stelle ich gern bereit.

Eydamos ·

Für meine Extensions habe ich nie mehrere StorageFolder gebraucht um Datensätze zu speichern. Sowas wird glaube ich auch eher selten genutzt. Meist benutzt man eher Kategorien und wählt dann im Plugin die Kategorien aus die angezeigt werden sollen (siehe tt_news, cal, uvm.).
Daher weiß ich nicht wie es geht.
Wenn ich wüsste wie es geht würde ich es posten.

Aber, es gibt Extensions die entsprechend mit PID's umgehen können, also habe ich einfach logisch geschlussfolgert das es ja anscheinend gehen muss.

Beim schreiben dieses Textes stellt sich mir nebenbei die Frage ob nicht der Fehler viel mehr bei deiner Programmierlogik als bei den PID's zu suchen ist, da die meisten Extension die mit vielen Daten umgehen müssen wie halt tt_news z.B. problemlos mit einem Storage Folder auskommen. Allerdings erlaube ich mir darüber kein Urteil, da ich dein Projekt und die Anforderungen nicht kenne.

Wie gesagt nur just my 2 cents, ich finde halt man sollte nicht einfach sagen das etwas schlecht ist, nur weil man nicht auf anhieb eine Lösung findet. Denn leider gibt es zu viele die einfach nur den ersten und den letzten Post lesen und sich dann darauf eine Meinung bilden.

hurikhan77 ·

Die Anforderungen sind einfach:

Kunde legt Reisen über den normalen Content Editor als Seiten an. Unten an der Seite müssen Meta-Daten ausgegeben werden, die jeweils passend zur Reise konfiguriert werden und völlig individuell sind - Kategorien fallen also flach (wäre sonst mein Ansatz gewesen).

Ursprünglich wollten wir diese Meta-Daten als Seitenelement einbinden, damit der Kunde alles aus einem Guss hat. Also machen wir das nun links über die Modulspalte, weil es ja anders nicht geht. Der Kunde wechselt also zwischen Seite (bzw. Liste) und unserem Modul. Deshalb brauchen wir die PID-Zuordnung. Ist vom Verfahren her ja auch noch genauso ergonomisch, da der Seitenselektor nicht zurückgesetzt wird, wenn man das Modul wechselt.

Die Meta-Daten enthalten Anweisungen für einen Formulargenerator, ähnlich wie Powermail - nur dass Powermail nicht Enduser-kompatibel ist (und mich beim ersten Anblick auch überfordert hat). Mit den Formularen werden später Reiseanmeldungen im Frontend abgefragt - und dort wird es ein wenig Javascript-Voodoo geben, in Abhängigkeit von Benutzereingaben blenden weiter unten Bereiche des Formulars aus, ein oder um - also sehr dynamisch (einen NonJS-Fallback muss es natürlich auch geben). Powermail hätte DAS nicht mal abbilden können. Zudem werden abhängig von Auswahlen Preise aufsummiert oder prozentuale Zuschläge berechnet.

Im Backend muss das Anlegen des Formulars möglichst einfach und schnell sein - ein ständiges Neuladen für jede neue Formularzeile wäre zu träge - also kann man hier nur was individuelles mit Ajax oder Javascript machen. Dafür ist Extbase mit seinem MVC ja eigentlich prädestiniert - legt einem dummerweise aber viele nur halbfertige oder noch nicht zu Ende gedachte "Features" in den Weg. Darauf bezog sich sicher auch das "unausgegoren" meines Vorredners - nicht auf die Existenz der Storage-PID-Spalte an sich (die Idee dafür ist klasse - grad in Bezug auf das Zusammenspiel mit der GUI und das Wechseln der Module).

Und ich glaube, solltest du einen zweiten Gedanken daran verschwenden wollen, musst auch du zugeben, dass nicht alle sinnvollen Möglichkeiten momentan (einfach) ausschöpfbar sind und es noch unausgegoren ist. Die ganze Storage-PID-Sache ist mit Extbase momentan noch zu statisch und unterstützt maximal das Konzept der "Container" wie z.B. tt_news das nutzt. Wir brauchen nun mal einen Container pro Seite, damit das sinnvoll nutzbar wird.

Wenn das Projekt fertig ist, poste ich gern einen Link und ggf. ein paar Screenshots vom Backend.

Eydamos schrieb

Wie gesagt nur just my 2 cents, ich finde halt man sollte nicht einfach sagen das etwas schlecht ist, nur weil man nicht auf anhieb eine Lösung findet.

Es ist aber mindestens genauso ungeschickt, seinem Gegenüber Faulheit oder Ahnungslosigkeit zu unterstellen. Da mir die meisten Foren zu umständlich sind, ist Google normalerweise immer mein erster Freund, und danach der zugrunde liegende Source-Code - und ich behaupte mal einfach, dass ich von den wiederum dort zugrunde liegenden Konzepten genug verstehe, auch wenn ich in Typo3 bisher kaum entwickelt habe.

oliver_g ·

Hallo Eydamos,

ich sehe hier kein Programmlogikfehler oder auch falsche Anforderungen seitens Hurikhan77. Es ist überhaupt nicht abwegig, verschiedene Objekte in unterschiedlichen Ordner (SysFolder) speichern zu wollen. Alle Datensätze in einer Seite reinklatschen ist auch nicht so optimal, da dies sehr schnell in Chaos ausarten kann.

Daher finde ich Hurikhan77s Anforderungen vollkommen legitim. Und ja, ich finde Extbase im Ansatz gut, ist aber an vielen Stellen unausgereift und nicht flexibel genug. Trotzdem momentan der beste Weg Extensions für Typo3 zu entwickeln.

Gruß
Oliver