Extbase Extensions - Snippets und Glossar: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
 
(31 dazwischenliegende Versionen von 4 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 +
Beinhaltet z.T. auch Fluid
 +
 +
== Siehe auch ==
 +
[[Extbase - Nützliche Funktionen und Libraries]]
 
== Hinweis neue Namespace Regelung für Klassen ==
 
== Hinweis neue Namespace Regelung für Klassen ==
 
[[Extbase Änderungen ab TYPO3 V6]]
 
[[Extbase Änderungen ab TYPO3 V6]]
  
 
== Glossar ==
 
== Glossar ==
 +
[[Extbase - Glossar]]
 +
 +
== Snippets Links ==
 +
http://typo3.org/documentation/snippets/
 +
== Mehrere Models in einem Formular / einer Action steuern ==
 +
== Rendering des Views steuern ==
 +
=== Serialisierte Daten nutzen ===
 +
Beispiel Narda:
  
===Extbase===
+
In einem Textfeld der Datenbank werden verschiedene Infos (hier Datumsangaben) gespeichert. Im Singleview sollen sie ausgegeben werden.
ist ein MVC Framework für die Extension entwicklung in TYPO3
+
Controller:
 +
<syntaxhighlight lang="php">
  
===FLOW3===
+
</syntaxhighlight>
- ist ein PHP-Framework, welches TYPO3 Version 5 verwenden wird.
+
Fluid Template
 +
<syntaxhighlight lang="html5">
 +
<td><f:format.date format="d.m.Y">{erpStatusChange}</f:format.date></td>
 +
<td><f:format.date format="d.m.Y">{dateOfReceipt}</f:format.date></td>
 +
<td><f:format.date format="d.m.Y">{quotationSent}</f:format.date></td>
 +
<td><f:format.date format="d.m.Y">{quotationApproved}</f:format.date></td>
 +
<td><f:format.date format="d.m.Y">{dateOfReturnShipment}</f:format.date></td>
  
===Fluid===
+
</syntaxhighlight>
- Template Engine ähnlich wie Smarty ab Version 5
 
  
===Namespace===  
+
=== Timestamp - crdate und tstamp nutzen ===
Im Model hinterlegt z.B. : namespace TripMaps\Slidercalc\Domain\Model; taucht in vielen Funktionen wieder auf.
+
[[Extbase - Timestamp nutzen]]
  
== Snippets Links ==
 
http://typo3.org/documentation/snippets/
 
== Rendering des Views steuern ==
 
 
=== Rendering verhindern ===
 
=== Rendering verhindern ===
 
Am Ende der Action wird implizit immer
 
Am Ende der Action wird implizit immer
Zeile 26: Zeile 41:
 
zurückgeben
 
zurückgeben
  
== Objekt-Abfragen steuern ==
+
== Objekt-Datenbank-Abfragen steuern ==
 
Das Ergebnis der findAll() Funktion im Controller läßt sich mit dem QueryInterface steuern.
 
Das Ergebnis der findAll() Funktion im Controller läßt sich mit dem QueryInterface steuern.
 
Z.B. kann man im Repository die Standardsortierung festlegen.
 
Z.B. kann man im Repository die Standardsortierung festlegen.
 +
 +
[[Extbase - Query Objekt]]
 +
 
[[Extbase - Sortierung und Abfrage von Objekten]]
 
[[Extbase - Sortierung und Abfrage von Objekten]]
 +
 +
== Objekte erstellen, löschen, bearbeiten ==
 +
[[Extbase - Objekte handeln]]
  
 
== TypoScript Konfiguration im Controller nutzen ==
 
== TypoScript Konfiguration im Controller nutzen ==
Zeile 43: Zeile 64:
 
PHP
 
PHP
 
  $valX = $this->settings['myXsetting'];
 
  $valX = $this->settings['myXsetting'];
 +
 +
== Property Mapper ==
 +
Ein Property Mapper hat die Aufgabe, die Daten, die von Formularen an den Webserver gesendet werden in die korrekten Variablentypen zu konvertieren.
 +
 +
Er sorgt auch dafür das die Propertys auf die richtigen Modelle und Tabellen gemappt werden.
 +
 +
http://www.typo3lexikon.de/typo3-tutorials/extensions/extbase/property-mapper.html
  
 
== E-Mails mit Extbase ==
 
== E-Mails mit Extbase ==
Zeile 48: Zeile 76:
  
 
http://www.benny-vs-web.de/typo3/extbase-fluid-zum-rendern-von-e-mail-templates-verwenden/
 
http://www.benny-vs-web.de/typo3/extbase-fluid-zum-rendern-von-e-mail-templates-verwenden/
 +
 +
[[Extbase - E-Mail / MailMessage]]
 +
 
== Lokalisierung - Language Files ==
 
== Lokalisierung - Language Files ==
  
Zeile 90: Zeile 121:
 
# Auf gewünschten View weiterleiten (z.B. ''$this->redirect('list');'' )
 
# Auf gewünschten View weiterleiten (z.B. ''$this->redirect('list');'' )
  
=== Auf Daten andererer Modelle / Repositorys im Controller zugreifen. (verknüpfte Daten auflisten) ===
+
=== Requestdaten verarbeiten ===
 +
==== Get / Post Vars ====
 +
$this->request->getArguments()
 +
$this->request->getArgument('variable')
 +
 
 +
$args = $this->request->getArguments();
 +
$showUid = $args['show'];
 +
 
 +
// Test if Argument is available
 +
$this->request->hasArgument('variable')
 +
 
 +
==== cObject ====
 +
//$cObjData = $this->request->getContentObjectData(); // deprecated
 +
$this->configurationManager->getContentObject()
 +
==== Redirect ====
 +
$this->redirect('show','Blog',NULL,array('blog'=>$blog));
 +
$this->redirect('nameOfAction','NameOfDomainModel',NULLorOtherExtName,array('objectNameToSend'=>$objectToSend));
 +
 
 +
=== Auf Daten von anderen Models / Repositorys im Controller zugreifen. Dependency Injection ===
 +
Will man auf Daten anderer Extensions zugreifen oder verknüpfte Daten komplett ohne ein Objekt des Aggregate Root (also die Haupttabelle) ausgeben muß man die Datenstruktur Injecten. Grundsätzlich kann man mit der Inject Methode aus jeder Extension heraus '''auf Daten anderer Extensions zugreifen'''.
 +
 
 +
'''Beispiel:'''
 
Im Controller steht wegen der strikten '''Trennung der Modelle''' erstmal das Repository (Die Datenstruktur) des Models zur Verfügung. Die verknüpften Daten (hier im Beispiels die Genres, gibt der View zwar über die Verknüpfung aus, das sind aber nur die mit dem jeweiligen Datensatz '''verknüpften Daten'''. Z.B. die Genres einer Band. Will man z.B. '''alle Genres im Listview der Bands''' ausgeben braucht man ein '''Repository der Genres und muß den Genre Controller in den Band Controller injecten'''. Dann kann man auf alle Funktionen des Genre Controllers auch aus dem Band Controller zugreifen. So bleibt auch alles sauber getrennt.
 
Im Controller steht wegen der strikten '''Trennung der Modelle''' erstmal das Repository (Die Datenstruktur) des Models zur Verfügung. Die verknüpften Daten (hier im Beispiels die Genres, gibt der View zwar über die Verknüpfung aus, das sind aber nur die mit dem jeweiligen Datensatz '''verknüpften Daten'''. Z.B. die Genres einer Band. Will man z.B. '''alle Genres im Listview der Bands''' ausgeben braucht man ein '''Repository der Genres und muß den Genre Controller in den Band Controller injecten'''. Dann kann man auf alle Funktionen des Genre Controllers auch aus dem Band Controller zugreifen. So bleibt auch alles sauber getrennt.
  
* eigenes Repository für verknüpfte Daten erstellen (z.B. Genre)
+
* eigenes '''Repository''' für verknüpfte Daten '''erstellen''' (z.B. Genre)
<pre>
+
<syntaxhighlight lang="php">
 
/**
 
/**
 
* genreRepository
 
* genreRepository
Zeile 102: Zeile 154:
 
*/
 
*/
 
protected $genreRepository = NULL;
 
protected $genreRepository = NULL;
</pre>
+
</syntaxhighlight>
* in gewünschten Controller (Hauptcontroller) injecten dazu innerhalb der Klasse folgendes hinzufügen:
+
*Im Controller (Hauptcontroller) deiner Extension injectest du das gewünschte Repository. Allerdings gibt es unterschiedliche Methoden je nachdem welche Typo3 Version du verwendest.
  
You can inject every repository of every installed extbase extension. Just add the dependency injection code to your controller. Depending on your TYPO3 version ist either:
+
====Dependency Injection 'TYPO3 ab 6.0====
 
+
<syntaxhighlight lang="php">
'''TYPO3 >= 6.0:'''
 
<pre>
 
 
/**
 
/**
 
  * @var \Vendor\Extension\Domain\Repository\SomeRepository
 
  * @var \Vendor\Extension\Domain\Repository\SomeRepository
Zeile 114: Zeile 164:
 
  */
 
  */
 
protected $someRepository;
 
protected $someRepository;
'''TYPO3 = 4.7:'''
+
</syntaxhighlight>
<pre>
+
 
 +
====Dependency Injection TYPO3 = 4.7 ====
 +
 
 +
<syntaxhighlight lang="php">
 
/**
 
/**
 
  * @var Tx_MyExtension_Domain_Repository_SomeRepository
 
  * @var Tx_MyExtension_Domain_Repository_SomeRepository
Zeile 121: Zeile 174:
 
  */
 
  */
 
  protected $someRepository;
 
  protected $someRepository;
</pre>
+
</syntaxhighlight>
'''TYPO3 < 4.7'''
+
 
<pre>
+
==== Dependency Injection TYPO3 vor 4.7 ====
 +
<syntaxhighlight lang="php">
 
/**
 
/**
 
  * @var Tx_MyExtension_Domain_Repository_SomeRepository
 
  * @var Tx_MyExtension_Domain_Repository_SomeRepository
Zeile 137: Zeile 191:
 
   $this->someRepository = $someRepository;
 
   $this->someRepository = $someRepository;
 
}
 
}
</pre>
+
</syntaxhighlight>
 
Jetzt kann man $this->someRepository mit all seinen Methoden auch in diesem Controller nutzen.
 
Jetzt kann man $this->someRepository mit all seinen Methoden auch in diesem Controller nutzen.
  
Zeile 163: Zeile 217:
 
Zu diesem Beispiel gehört der Controller unter
 
Zu diesem Beispiel gehört der Controller unter
 
  Classes/Controller/MailformController.php
 
  Classes/Controller/MailformController.php
 +
 +
==Domainmodel Beispiele ==
 +
=== M:N Verbindung komplett===
 +
[[Extbase - m:n Verknüpfung]]
  
 
== Diverse ==
 
== Diverse ==
Zeile 256: Zeile 314:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Zugriff auf TypoScript ==
+
== TypoScript und TSconfig ==
 +
=== Zugriff auf TypoScript ===
 +
Auf die TypoScript Einstellungen unter:
 +
<syntaxhighlight lang="typoscript">
 +
plugin.tx_myextname {
 +
settings{
 +
meinWert = 123   
 +
}
 +
}
 +
</syntaxhighlight>
 +
Kann man einfach im Controller mittels $this->settings['meinWert']; zugreifen. Beispiel
 +
$adminmail = $this->settings['adminMail'];
 +
 
 +
Man kann mit dem Configuration Manager auch auf andere Einstellungen zugreifen:
 +
 
 
https://typo3.org/api/typo3cms/class_t_y_p_o3_1_1_c_m_s_1_1_extbase_1_1_configuration_1_1_configuration_manager.html#ac6b6323862565409eddac516dca08c10
 
https://typo3.org/api/typo3cms/class_t_y_p_o3_1_1_c_m_s_1_1_extbase_1_1_configuration_1_1_configuration_manager.html#ac6b6323862565409eddac516dca08c10
 
<pre>
 
<pre>
Zeile 265: Zeile 337:
 
)
 
)
 
</pre>
 
</pre>
 +
 +
=== TSConfig automatisch in Extensions laden ===
 +
Es gibt zwei Möglichkeiten eine ab Version 7.
 +
# Entweder automatisches Laden über ext_localconf.php und addPageTSConfig.
 +
# Oder über eine Datei in Configuration/TCA/meineDatei.php und registerPageTSConfigFile. Hierbei müssen geladene Konfigurationen noch in den Seiteneigenschaften eingebunden werden (ähnlich wie Static Templates)
 +
 +
Sehr schön finde ich folgende Möglichkeit. Für Typo3 v6 (oder kleiner) gibt man in der ext_localconf.php an wo das TSconfig liegt. In v7 kann man unter Configuration/TCA[/Overrides]/ Dateien ablegen. So kann man mit v6 und v7 kompatible Extensions erstellen:
 +
 +
typo3conf/myextkey/ext_localconf.php
 +
<syntaxhighlight lang="php">
 +
<?php
 +
if (!defined('TYPO3_MODE')) {
 +
die('Access denied.');
 +
}
 +
/***************
 +
* Make the extension configuration accessible
 +
*/
 +
if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY])) {
 +
$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY] = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY]);
 +
}
 +
/***********
 +
* PageTs
 +
*/
 +
// for vers. >= 7 see Configuration/TCA/Overrides
 +
if (version_compare(TYPO3_version,'7.0.0','<')) {
 +
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig('<INCLUDE_TYPOSCRIPT: source="FILE:EXT:gbmaterialize/Configuration/PageTSconfig/tsconfig.ts">');
 +
}
 +
/***************
 +
* Reset extConf array to avoid errors
 +
*/
 +
if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY])) {
 +
$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY] = serialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY]);
 +
}
 +
?>
 +
</syntaxhighlight>
 +
 +
typo3conf/myext/Configuration/TCA/Overrides/pages.php
 +
<syntaxhighlight lang="php">
 +
<?php
 +
defined('TYPO3_MODE') or die();
 +
// for vers. <7 see ext_localconf.php
 +
if (version_compare(TYPO3_version,'6.2.99','>')) {
 +
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerPageTSConfigFile(
 +
'gbmaterialize',
 +
'Configuration/PageTSconfig/tsconfig.ts',
 +
'Materialize BE Grid'
 +
);
 +
} else {}
 +
 +
if (version_compare(TYPO3_version,'7.3.99','>')) {
 +
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerPageTSConfigFile(
 +
'gbmaterialize',
 +
'Configuration/PageTSconfig/be_layouts.ts',
 +
'GBMaterialize BE Layouts'
 +
);
 +
</syntaxhighlight>
 +
Hier ein Beispiel für eine tsconfig.ts für die obigen Code Snippets
 +
<syntaxhighlight lang="typoscript">
 +
# Grid elements Backend Layouts
 +
tx_gridelements.setup.materialize_2col {
 +
title = Zwei Spalten
 +
description = Ein Element um Spalten darstellen zu können.
 +
flexformDS = FILE:EXT:gbmaterialize/Configuration/FlexForm/materialize_columns_2col.xml
 +
 +
config {
 +
colCount = 2
 +
rowCount = 1
 +
...
 +
</syntaxhighlight>
  
 
== Daten aus anderen Extensions ==
 
== Daten aus anderen Extensions ==
=== Zugriff auf fe_user ===
+
=== Zugriff auf Frontend User (feuser) ===
 
[[Extbase - Zugriff auf die fe_user Tabelle]]
 
[[Extbase - Zugriff auf die fe_user Tabelle]]
  
Zeile 486: Zeile 627:
  
 
== Mehrere Modelle in einem View ==
 
== Mehrere Modelle in einem View ==
=== Daten mit mehreren nicht persistenten Daten in Sessions ===
+
=== Übergabe mehrerer Objekte aus einem View ===
 +
In Fluid
 +
<f:link.action action="newMetadevice" arguments="{rma : rma, device : device}">add</f:link.action>
 +
Im Controller
 +
1. Direkt im Header
 +
public function createDeviceAction(\Geobit\Gbrma\Domain\Model\Rma $rma,\Geobit\Gbrma\Domain\Model\Device $device){...}
 +
Hier können auch komplette Objekte übergeben werden
 +
2. Im Controller mit getArgument()
 +
$deviceClassUid = intval($this->request->getArgument('deviceClassUid'));
 +
Hier werden nur Get-Post Variablen ausgelesen wie früher die piVars.
 +
 
 +
=== Datenübergabe in Sessions ===
 +
In diesem Beispiel werden Datenobjekte als serialisierter String in einer Session gespeichert.
 +
 
 
http://stackoverflow.com/questions/27821750/multiple-objects-in-one-fluid-form (2015-03)
 
http://stackoverflow.com/questions/27821750/multiple-objects-in-one-fluid-form (2015-03)
  
Zeile 494: Zeile 648:
  
  
<pre>
+
<syntaxhighlight lang="php">
 
<?php
 
<?php
 
namespace derhansen\ValidationExamplesNew\Controller;
 
namespace derhansen\ValidationExamplesNew\Controller;
Zeile 730: Zeile 884:
 
}
 
}
 
?>
 
?>
</pre>
+
</syntaxhighlight>

Aktuelle Version vom 28. Juli 2016, 10:22 Uhr

Beinhaltet z.T. auch Fluid

Siehe auch[Bearbeiten]

Extbase - Nützliche Funktionen und Libraries

Hinweis neue Namespace Regelung für Klassen[Bearbeiten]

Extbase Änderungen ab TYPO3 V6

Glossar[Bearbeiten]

Extbase - Glossar

Snippets Links[Bearbeiten]

http://typo3.org/documentation/snippets/

Mehrere Models in einem Formular / einer Action steuern[Bearbeiten]

Rendering des Views steuern[Bearbeiten]

Serialisierte Daten nutzen[Bearbeiten]

Beispiel Narda:

In einem Textfeld der Datenbank werden verschiedene Infos (hier Datumsangaben) gespeichert. Im Singleview sollen sie ausgegeben werden. Controller:

Fluid Template

<td><f:format.date format="d.m.Y">{erpStatusChange}</f:format.date></td>
<td><f:format.date format="d.m.Y">{dateOfReceipt}</f:format.date></td>
<td><f:format.date format="d.m.Y">{quotationSent}</f:format.date></td>
<td><f:format.date format="d.m.Y">{quotationApproved}</f:format.date></td>
<td><f:format.date format="d.m.Y">{dateOfReturnShipment}</f:format.date></td>

Timestamp - crdate und tstamp nutzen[Bearbeiten]

Extbase - Timestamp nutzen

Rendering verhindern[Bearbeiten]

Am Ende der Action wird implizit immer

return $this->view->render(); 

ausgeführt (auch wenn man es nicht schreibt). Will man das verhindern muß man

return false; 

zurückgeben

Objekt-Datenbank-Abfragen steuern[Bearbeiten]

Das Ergebnis der findAll() Funktion im Controller läßt sich mit dem QueryInterface steuern. Z.B. kann man im Repository die Standardsortierung festlegen.

Extbase - Query Objekt

Extbase - Sortierung und Abfrage von Objekten

Objekte erstellen, löschen, bearbeiten[Bearbeiten]

Extbase - Objekte handeln

TypoScript Konfiguration im Controller nutzen[Bearbeiten]

Hinweis zu Settings in TypoScript[Bearbeiten]

Im Action Controller und im Fluid Template sind nur die Objekte über $this->settings bzw. settings.objektname sichtbar die in plugin.tx_extname.settings liegen.

TypoScript

plugin.tx_some-extname.settings {
    myXsetting = XXXX
}

PHP

$valX = $this->settings['myXsetting'];

Property Mapper[Bearbeiten]

Ein Property Mapper hat die Aufgabe, die Daten, die von Formularen an den Webserver gesendet werden in die korrekten Variablentypen zu konvertieren.

Er sorgt auch dafür das die Propertys auf die richtigen Modelle und Tabellen gemappt werden.

http://www.typo3lexikon.de/typo3-tutorials/extensions/extbase/property-mapper.html

E-Mails mit Extbase[Bearbeiten]

http://t3-developer.com/extbase-fluid/extensions-erweitern/e-mail-versand-aus-extensions/mailversand/

http://www.benny-vs-web.de/typo3/extbase-fluid-zum-rendern-von-e-mail-templates-verwenden/

Extbase - E-Mail / MailMessage

Lokalisierung - Language Files[Bearbeiten]

Im Extbase Controller lokalisieren[Bearbeiten]

Z.B. bei Fehlermeldungen. flashMessages oder speziellen Ausgaben

Tx_Extbase_Utility_Localization::translate($langkey,$extensionName)

$extensionName = Extbase name (UpperCammelCase ohen Unterstriche)

$langkey muss der locallang.xml datei bzw. xlf hinzugefügen.

<label index="tx_t3easyplugins_domain_model_plugin.createdSuccessful">Your new Plugin was created.</label>

Unten ein kleines Beispiel. Tx_Extbase_Utility_Localization::translate

/**
 * action create
 *
 * @param $newEntry
 * @return void
 */
public function createAction(Tx_T3easyPlugins_Domain_Model_Plugin $newEntry) {
    $this->entryRepository->add($newEntry);
    $this->flashMessageContainer->add(Tx_Extbase_Utility_Localization::translate('tx_t3easyplugins_domain_model_Plugin.createdSuccessful', 'T3easyPlugins'));
    $this->redirect('list');
}

locallang.xml

...
<label index="tx_t3easyplugins_domain_model_plugin.createdSuccessful">Your new Plugin was created.</label>
...

Actions[Bearbeiten]

Controller und Actions Basics[Bearbeiten]

http://docs.typo3.org/typo3cms/ExtbaseFluidBook/7-Controllers/1-Creating-Controllers-and-Actions.html

Neue Action realisieren[Bearbeiten]

  1. Action registrieren (localconf.php)
  2. Methode für die Action schreiben (im Controller des Objektes)
  3. Auf gewünschten View weiterleiten (z.B. $this->redirect('list'); )

Requestdaten verarbeiten[Bearbeiten]

Get / Post Vars[Bearbeiten]

$this->request->getArguments()
$this->request->getArgument('variable')
$args = $this->request->getArguments();
$showUid = $args['show'];
// Test if Argument is available
$this->request->hasArgument('variable')

cObject[Bearbeiten]

//$cObjData = $this->request->getContentObjectData(); // deprecated
$this->configurationManager->getContentObject()

Redirect[Bearbeiten]

$this->redirect('show','Blog',NULL,array('blog'=>$blog));
$this->redirect('nameOfAction','NameOfDomainModel',NULLorOtherExtName,array('objectNameToSend'=>$objectToSend));

Auf Daten von anderen Models / Repositorys im Controller zugreifen. Dependency Injection[Bearbeiten]

Will man auf Daten anderer Extensions zugreifen oder verknüpfte Daten komplett ohne ein Objekt des Aggregate Root (also die Haupttabelle) ausgeben muß man die Datenstruktur Injecten. Grundsätzlich kann man mit der Inject Methode aus jeder Extension heraus auf Daten anderer Extensions zugreifen.

Beispiel: Im Controller steht wegen der strikten Trennung der Modelle erstmal das Repository (Die Datenstruktur) des Models zur Verfügung. Die verknüpften Daten (hier im Beispiels die Genres, gibt der View zwar über die Verknüpfung aus, das sind aber nur die mit dem jeweiligen Datensatz verknüpften Daten. Z.B. die Genres einer Band. Will man z.B. alle Genres im Listview der Bands ausgeben braucht man ein Repository der Genres und muß den Genre Controller in den Band Controller injecten. Dann kann man auf alle Funktionen des Genre Controllers auch aus dem Band Controller zugreifen. So bleibt auch alles sauber getrennt.

  • eigenes Repository für verknüpfte Daten erstellen (z.B. Genre)
	/**
	 * genreRepository
	 *
	 * @var \Geobit\Gbbandpass\Domain\Repository\GenreRepository
	 * @inject
	 */
	protected $genreRepository = NULL;
  • Im Controller (Hauptcontroller) deiner Extension injectest du das gewünschte Repository. Allerdings gibt es unterschiedliche Methoden je nachdem welche Typo3 Version du verwendest.

Dependency Injection 'TYPO3 ab 6.0[Bearbeiten]

/**
 * @var \Vendor\Extension\Domain\Repository\SomeRepository
 * @inject
 */
protected $someRepository;

Dependency Injection TYPO3 = 4.7[Bearbeiten]

/**
 * @var Tx_MyExtension_Domain_Repository_SomeRepository
 * @inject
 */
 protected $someRepository;

Dependency Injection TYPO3 vor 4.7[Bearbeiten]

/**
 * @var Tx_MyExtension_Domain_Repository_SomeRepository
 */
 protected $someRepository;

/**
 * Inject SomeRepository
 * @param Tx_MyExtension_Domain_Repository_SomeRepository $someRepository
 * @return void
 */
public function injectSomeRepository(Tx_MyExtension_Domain_Repository_SomeRepository $someRepository) {
  $this->someRepository = $someRepository;
}

Jetzt kann man $this->someRepository mit all seinen Methoden auch in diesem Controller nutzen.

Hinweis: Nach Änderung System Cache löschen !

Controller-Action Kombinationen für Frontend-Plugins definieren[Bearbeiten]

http://docs.typo3.org/typo3cms/ExtbaseFluidBook/b-ExtbaseReference/Index.html

In ext_localconf.php sind erlaubte Actions hinterlegt. Der erste Eintrag ist die Default-Action.

\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
	'Geobit.' . $_EXTKEY,
	'Mailformtest',
	array(
		'Mailform' => 'list, show, new, create',
		
	),
	// non-cacheable actions
	array(
		'Mailform' => 'create, ',
		
	)
);

Zu diesem Beispiel gehört der Controller unter

Classes/Controller/MailformController.php

Domainmodel Beispiele[Bearbeiten]

M:N Verbindung komplett[Bearbeiten]

Extbase - m:n Verknüpfung

Diverse[Bearbeiten]

Actions anlegen[Bearbeiten]

Im Controller:

/**
 * action list
 *
 * @return void
 */
public function listAction() {
	$myextname = $this->myextRepository->findAll();
	$this->view->assign('myextname', $myextname);
}

addFlashMessage[Bearbeiten]

Im Controller

 $this->addFlashMessage('This is a simple success message');
 $this->addFlashMessage('The message body', 'Message title', \TYPO3\CMS\Core\Messaging\AbstractMessage::OK, TRUE);
 $this->addFlashMessage('<strong>HTML-Messageplement</strong>', '', \TYPO3\CMS\Core\Messaging\AbstractMessage::ERROR);

Existierende Extbase Klassen erweitern[Bearbeiten]

( Früher XCLASS ) - http://blog.sebastiaandejonge.com/articles/2013/june/11/class-extension-in-extbase/

Default Sortierung in Extbase[Bearbeiten]

Beispiel aus Slidercalc[Bearbeiten]

/**
 * The repository for Sliders
 */
class SliderRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
	protected $defaultOrderings = array(
		'category.sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
		'sorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
		//'date' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
	);
	
}

Quelle: http://t3n.de/magazin/zehn-tipps-tricks-extbase-fluid-227639/2/ (11/2014)

Default-Sortierung im Repository

Nicht unbedingt unbekannt, aber weitestgehend ungenutzt ist ein Feature, welches in Extbase 1.3 hinzugekommen ist: Im Repository besteht die Möglichkeit, das Ergebnis nach bestimmten Feldern aufsteigend oder absteigend zu sortieren. Dies wird beispielsweise mittels „

$query->setOrderings(array('name' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING));

erledigt.

Um dies nicht für jede einzelne Repository-Funktion einstellen zu müssen, gibt es die Eigenschaft defaultOrderings:

Im Repository

protected $defaultOrderings = array ('name' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING);

Debugging[Bearbeiten]

Fehlermeldung class_parents(): object or string expected[Bearbeiten]

Nachdem man neue Properties hinzugefügt hat kommt obige Fehlermeldung. Dies ist ein Bug in Extbase. Nur Truncating cf_extbase_reflection works. (Bei 4.5 die Extbase Cachetabellen leeren)

Debugging im Controller[Bearbeiten]

Beispiel[Bearbeiten]

print \TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump( $this );

Beispiel[Bearbeiten]

t3lib_utility_Debug::debug($var, 'Debug: ' . __FILE__ . ' in Line: ' . __LINE__);
 
# namespaces
\TYPO3\CMS\Core\Utility\DebugUtility::debug($var, 'Debug: ' . __FILE__ . ' in Line: ' . __LINE__);

Beispiel[Bearbeiten]

Tx_Extbase_Utility_Debugger::var_dump($var);
 
# namespaces
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($var);

Debugging wenn keine Datensätze gefunden werden[Bearbeiten]

Im Repository kann man das Queryinterface überschreiben und so z.B. die Abfrage der storage Page unterbinden (alle werden ausgegeben). Auch Fehler im sql werden sichtbar.

/**
* @return QueryInterface
*/
public function createQuery(){
$query = parent::createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
return $query;
}

TypoScript und TSconfig[Bearbeiten]

Zugriff auf TypoScript[Bearbeiten]

Auf die TypoScript Einstellungen unter:

plugin.tx_myextname {
	settings{
		meinWert = 123    
	}
}

Kann man einfach im Controller mittels $this->settings['meinWert']; zugreifen. Beispiel

$adminmail = $this->settings['adminMail'];

Man kann mit dem Configuration Manager auch auf andere Einstellungen zugreifen:

https://typo3.org/api/typo3cms/class_t_y_p_o3_1_1_c_m_s_1_1_extbase_1_1_configuration_1_1_configuration_manager.html#ac6b6323862565409eddac516dca08c10

getConfiguration	(
 	$configurationType,
 	$extensionName = NULL,
 	$pluginName = NULL 
)	

TSConfig automatisch in Extensions laden[Bearbeiten]

Es gibt zwei Möglichkeiten eine ab Version 7.

  1. Entweder automatisches Laden über ext_localconf.php und addPageTSConfig.
  2. Oder über eine Datei in Configuration/TCA/meineDatei.php und registerPageTSConfigFile. Hierbei müssen geladene Konfigurationen noch in den Seiteneigenschaften eingebunden werden (ähnlich wie Static Templates)

Sehr schön finde ich folgende Möglichkeit. Für Typo3 v6 (oder kleiner) gibt man in der ext_localconf.php an wo das TSconfig liegt. In v7 kann man unter Configuration/TCA[/Overrides]/ Dateien ablegen. So kann man mit v6 und v7 kompatible Extensions erstellen:

typo3conf/myextkey/ext_localconf.php

<?php
if (!defined('TYPO3_MODE')) {
	die('Access denied.');
}
/***************
 * Make the extension configuration accessible
 */
if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY])) {
	$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY] = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY]);
}
/***********
 * PageTs
 */
// for vers. >= 7 see Configuration/TCA/Overrides
if (version_compare(TYPO3_version,'7.0.0','<')) {
	\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig('<INCLUDE_TYPOSCRIPT: source="FILE:EXT:gbmaterialize/Configuration/PageTSconfig/tsconfig.ts">');
}
/***************
 * Reset extConf array to avoid errors
 */
if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY])) {
	$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY] = serialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY]);
}
?>

typo3conf/myext/Configuration/TCA/Overrides/pages.php

<?php
defined('TYPO3_MODE') or die();
// for vers. <7 see ext_localconf.php
if (version_compare(TYPO3_version,'6.2.99','>')) {
	\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerPageTSConfigFile(
		'gbmaterialize',
		'Configuration/PageTSconfig/tsconfig.ts',
		'Materialize BE Grid'
	);
} else {}

if (version_compare(TYPO3_version,'7.3.99','>')) {
	\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerPageTSConfigFile(
		'gbmaterialize',
		'Configuration/PageTSconfig/be_layouts.ts',
		'GBMaterialize BE Layouts'
	);

Hier ein Beispiel für eine tsconfig.ts für die obigen Code Snippets

# Grid elements Backend Layouts
tx_gridelements.setup.materialize_2col {
	title = Zwei Spalten
	description = Ein Element um Spalten darstellen zu können.
	flexformDS = FILE:EXT:gbmaterialize/Configuration/FlexForm/materialize_columns_2col.xml

	config {
		colCount = 2
		rowCount = 1
...

Daten aus anderen Extensions[Bearbeiten]

Zugriff auf Frontend User (feuser)[Bearbeiten]

Extbase - Zugriff auf die fe_user Tabelle

Zugriff auf andere Extensions[Bearbeiten]

Extbase - Zugriff auf Tabellen anderer Extbase Extensions

AJAX mit Extbase[Bearbeiten]

AJAX über neuen Page Type[Bearbeiten]

Quelle: http://t3-developer.com/extbase-fluid/extensions-erweitern/ajax-in-extensions/ajaxcalls-mit-pagetype/ (2014/12)

Die Verwendung eines eigenen page Types für Ajax Calls ist relativ simpel. Zunächst müsst ihr euer Extensionsetup um einen neuen PageType erweitern. Die PageType Nummer muss einmalig in der Installation sein, also ggf. bereits vergebene PageTypes für RSS, Sitemaps, Print & Co beachten.

Extensionsetup[Bearbeiten]

Bitte beachtet das ihr in der letzten Zeile eure den Extensionnamen ohne 'tx_' Prefix angeben müsst!

TypoScript

ajaxCall = PAGE 
ajaxCall { 
typeNum = 999 
     config.disableAllHeaderCode = 1 
     config.metaCharset = UTF-8 
    10 = COA 
    10 < tt_content.list.20.myextension_myplugin 
 }

Der AjaxCall in jQuery

$('#jq-send').click(function(e) { 
    $.ajax({ 
        var controller = tx_myExt_myplugin[controller]= blabla; 
        var action = tx_myExt_myplugin[action]= meineControllerFunction; // ohne Action am Ende 
        var pagetype = 999;
        var path = $(location).attr('href');

        url: path +  '/?' + controller + '&' + action + '&type=' + pagetype 
        //optionale Parameter 
        data: 'useruid=' + useruid, 

        success: function(result) { 
            console.log(result); 
            //hier kommen eure Anweisungen rein
        }, 
        error: function(error) { 
            console.log(error); 
        } 
    }); 
});

Ein Beispiel findet ihr auch in meiner Blogextension "multiblog" auf Github: ajaxCall in Blogextension

Ajax Function im Controller[Bearbeiten]

Die Controllerfunction muss natürlich wie jede Action in der ext_localconf.php registriert sein. Innerhalb dieser Action steht euch die ganz normale Extbase Umgebung zur Verfügung, also alles das was ihr in 'normalen' Funktionen auch habt (injected Repositories, mapped Tables, settings etc.) Genau das ist der Unterschied zu einem AjaxCall über eID, das komplette TSFE ist geladen.

Am Ende der Funktion müsst Ihr euch nur entscheiden, was Ihr zurückgeben wollt:

Rückgabe eine json strings (z.B. Ergebnisarray):

return json_encode($myArray);

Rückgabe eines kompletten Views als html string. Am Ende der Ajax Funktion im Controller setzt Ihr ganz normal euren View (Template muss vorhanden sein):

$this->view->assign('myAjaxAction, $values);

Keinerlei Rückgabe z.B wenn Ihr nur Daten nur für einen Counter speichert:

exit;

Innerhalb von der jQuery Funktion success:function(result) { } wird dann das Ergebnis ausgewertet. Die vom Controller zurückgegebenen Werte stehen in der Variablen result zur Verfügung.

AJAX Call über eid Mechanismus[Bearbeiten]

Quelle: http://t3-developer.com/extbase-fluid/extensions-erweitern/ajax-in-extensions/ajax-dispatcher-eid-in-typo3-61/ (2014/12)

Ajax Dispatcher für TYPO3 6.2 - wichtige Hinweise!

Damit das nachfolgende Script auch unter TYPO3 6.2.3 funktioniert, müssen folgende Zeilen geändert werden:

Zeile 101:

\TYPO3\CMS\Core\Core\Bootstrap::getInstance();

Siehe auch forge.typo3.org/issues/59070.

Ajax Dispaytcher für TYPO3 6.1 und Namespaces. Die Datei ist getestet und läuft auch ;). Ihr müsst in Zeile 82 + 83 den von Euch benutzen Vendor und Extension Namen einsetzten.

Siehe auch alle weiteren Angaben im Kommentarbereich des Dispatchers.

<?php
/** *************************************************************
*
* Extbase Dispatcher for Ajax Calls TYPO3 6.1 namespaces
*
* IMPORTANT Use this script only in Extensions with namespaces
*
* Klaus Heuer <klaus.heuer@t3-developer.com>
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
* ************************************************************* */
/** ************************************************************
* Usage of this script:
*
* - Copy this script in your Extension Dir in the Folder Classes
* - Set the Vendor and Extension Name in Line 82 + 83
* - Include the next line in the ext_localconf.php, change the ext name!
* - $TYPO3_CONF_VARS['FE']['eID_include']['ajaxDispatcher'] = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('myExtension').'Classes/EidDispatcher.php';
*
* Use for Ajax Calls in your jQuery Code:
*
* $('.jqAjax').click(function(e) {
* var uid = $(this).find('.uid').html();
* var storagePid = '11';
*
* $.ajax({
* async: 'true',
* url: 'index.php',
* type: 'POST',
*
* data: {
*     eID: "ajaxDispatcher",
*     request: {
*          pluginName: 'patsystem',
*          controller: 'Todo',
*          action: 'findTodoByAjax',
*          arguments: {
*               'uid': uid,
*               'storagePid': storagePid
*               }
*           }
*      },
*      dataType: "json",
*
*      success: function(result) {
*           console.log(result);
*      },
*      error: function(error) {
*           console.log(error);
*      }
* });
*************************************************************** */
/**
* Gets the Ajax Call Parameters
*/
$ajax = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('request');
/**
* Set Vendor and Extension Name
*
* Vendor Name like your Vendor Name in namespaces
* ExtensionName in upperCamelCase
*/
$ajax['vendor'] = 'T3Developer';
$ajax['extensionName'] = 'ProjectsAndTasks';
/**
* @var $TSFE \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
*/
$TSFE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController', $TYPO3_CONF_VARS, 0, 0);
\TYPO3\CMS\Frontend\Utility\EidUtility::initLanguage();
// Get FE User Information
$TSFE->initFEuser();
// Important: no Cache for Ajax stuff
$TSFE->set_no_cache();
//$TSFE->checkAlternativCoreMethods();
$TSFE->checkAlternativeIdMethods();
$TSFE->determineId();
$TSFE->initTemplate();
$TSFE->getConfigArray();
\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->loadConfigurationAndInitialize();
$TSFE->cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer');
$TSFE->settingLanguage();
$TSFE->settingLocale();
/**
* Initialize Database
*/
\TYPO3\CMS\Frontend\Utility\EidUtility::connectDB();
/**
* @var $objectManager \TYPO3\CMS\Extbase\Object\ObjectManager
*/
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
/**
* Initialize Extbase bootstap
*/
$bootstrapConf['extensionName'] = $ajax['extensionName'];
$bootstrapConf['pluginName'] = $ajax['pluginName'];
$bootstrap = new TYPO3\CMS\Extbase\Core\Bootstrap();
$bootstrap->initialize($bootstrapConf);
$bootstrap->cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tslib_cObj');
/**
* Build the request
*/
$request = $objectManager->get('TYPO3\CMS\Extbase\Mvc\Request');
$request->setControllerVendorName($ajax['vendor']);
$request->setcontrollerExtensionName($ajax['extensionName']);
$request->setPluginName($ajax['pluginName']);
$request->setControllerName($ajax['controller']);
$request->setControllerActionName($ajax['action']);
$request->setArguments($ajax['arguments']);
$response = $objectManager->create('TYPO3\CMS\Extbase\Mvc\ResponseInterface');
$dispatcher = $objectManager->get('TYPO3\CMS\Extbase\Mvc\Dispatcher');
$dispatcher->dispatch($request, $response);
echo $response->getContent();
//die();
?>

Mehrere Modelle in einem View[Bearbeiten]

Übergabe mehrerer Objekte aus einem View[Bearbeiten]

In Fluid

<f:link.action action="newMetadevice" arguments="{rma : rma, device : device}">add</f:link.action>

Im Controller 1. Direkt im Header

public function createDeviceAction(\Geobit\Gbrma\Domain\Model\Rma $rma,\Geobit\Gbrma\Domain\Model\Device $device){...}

Hier können auch komplette Objekte übergeben werden 2. Im Controller mit getArgument()

$deviceClassUid = intval($this->request->getArgument('deviceClassUid'));

Hier werden nur Get-Post Variablen ausgelesen wie früher die piVars.

Datenübergabe in Sessions[Bearbeiten]

In diesem Beispiel werden Datenobjekte als serialisierter String in einer Session gespeichert.

http://stackoverflow.com/questions/27821750/multiple-objects-in-one-fluid-form (2015-03)

In order to pass non persistent objects between multiple actions, I would suggest that you store the objects serialized in a TYPO3 session variable. Doing so, you can restore the objects in the target action.

Below you find a working example which can also be found here. https://github.com/derhansen/extbase_validation_new_pm/blob/master/Classes/Controller/MultipleStepsController.php


<?php
namespace derhansen\ValidationExamplesNew\Controller;

/***************************************************************
 *  Copyright notice
 *
 *  (c) 2013 Torben Hansen <derhansen@gmail.com>
 *
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/

/**
 * Multiple Steps Controller
 *
 * @package validation_examples_new
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
 *
 */
class MultipleStepsController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {

    /**
     * addressdataRepository
     *
     * @var \derhansen\ValidationExamplesNew\Domain\Repository\AddressdataRepository
     * @inject
     */
    protected $addressdataRepository;

    /**
     * API Service
     *
     * @var \derhansen\ValidationExamplesNew\Service\ExternalApiService
     * @inject
     */
    protected $apiService;

    /**
     * Step1
     *
     * @param \derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data
     * @dontvalidate $step1data
     */
    public function step1Action(\derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data = NULL) {
        /* Check if step1data is available in session */
        if ($GLOBALS['TSFE']->fe_user->getKey('ses', 'step1data') && $step1data == NULL) {
            $step1data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step1data'));
        }

        $this->view->assign('step1data', $step1data);
    }

    /**
     * Step1 redirect action
     *
     * @param \derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data
     */
    public function step1redirectAction(\derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data) {
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'step1data', serialize($step1data));
        $GLOBALS['TSFE']->fe_user->storeSessionData();

        $this->redirect('step2');
    }

    /**
     * Step2
     *
     * @param \derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data
     * @dontvalidate $step2data
     */
    public function step2Action(\derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data = NULL) {
        /* Check if step2data is available in session */
        if ($GLOBALS['TSFE']->fe_user->getKey('ses', 'step2data') && $step2data == NULL) {
            $step2data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step2data'));
        }

        /* Set external validations errors if available */
        $this->setApiValidationErrors('step2');

        $this->view->assign('step2data', $step2data);
    }

    /**
     * Step2 redirect action
     *
     * @param \derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data
     */
    public function step2redirectAction(\derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data) {
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'step2data', serialize($step2data));
        $GLOBALS['TSFE']->fe_user->storeSessionData();

        $this->redirect('step3');
    }


    /**
     * Step3
     *
     * @param \derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data
     * @dontvalidate $step3data
     */
    public function step3Action(\derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data = NULL) {
        /* Check if step3data is available in session */
        if ($GLOBALS['TSFE']->fe_user->getKey('ses', 'step3data') && $step3data == NULL) {
            $step3data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step3data'));
        }

        /* Set external validations errors if available */
        $this->setApiValidationErrors('step3');

        $this->view->assign('step3data', $step3data);
    }

    /**
     * Step3 redirect action
     *
     * @param \derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data
     */
    public function step3redirectAction(\derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data) {
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'step3data', serialize($step3data));
        $GLOBALS['TSFE']->fe_user->storeSessionData();

        $this->redirect('create');
    }

    /**
     * Create Action
     *
     * @return void
     */
    public function createAction() {
        $addressdata = $this->getAddressdataFromSession();

        /* get validation results from API */
        $apiresults = $this->apiService->validateMultipleSteps($addressdata);
        if (count($apiresults) > 0) {
            /* Save results to a session variable */
            $GLOBALS['TSFE']->fe_user->setKey('ses', 'apiresults', $apiresults);
            $GLOBALS['TSFE']->fe_user->storeSessionData();

            /* Redirect to step with validation errors */
            if (array_key_exists('step2', $apiresults)) {
                $this->redirect('step2');
            }
            if (array_key_exists('step3', $apiresults)) {
                $this->redirect('step3');
            }
        }

        $this->addressdataRepository->add($addressdata);
        $this->cleanUpSessionData();

        $this->view->assign('message', 'Addressdata has been created');
    }

    /**
     * Collects the addressdata from the multiple steps form stored in session variables
     * and returns an addressdata object.
     *
     * @return \derhansen\ValidationExamplesNew\Domain\Model\Addressdata
     */
    protected function getAddressdataFromSession() {
        /** @var \derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data */
        $step1data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step1data'));

        /** @var \derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data */
        $step2data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step2data'));

        /** @var \derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data */
        $step3data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step3data'));

        /** @var \derhansen\ValidationExamplesNew\Domain\Model\Addressdata $addressData */
        $addressData = $this->objectManager->get('derhansen\ValidationExamplesNew\Domain\Model\Addressdata');
        $addressData->setFirstname($step1data->getFirstname());
        $addressData->setLastname($step1data->getLastname());
        $addressData->setStreet($step2data->getStreet());
        $addressData->setStreetnr($step2data->getStreetnr());
        $addressData->setZip($step3data->getZip());
        $addressData->setCity($step3data->getCity());

        return $addressData;
    }

    /**
     * Removes all session variables from the multiple steps form
     *
     * @return void
     */
    protected function cleanUpSessionData() {
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'step1data', '');
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'step2data', '');
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'step3data', '');
        $GLOBALS['TSFE']->fe_user->setKey('ses', 'apiresults', '');
        $GLOBALS['TSFE']->fe_user->storeSessionData();
    }

    /**
     * Sets validation errors for fields in the given step
     *
     * @param string $step The step
     * @return void
     */
    protected function setApiValidationErrors($step) {
        $apiresults = $GLOBALS['TSFE']->fe_user->getKey('ses', 'apiresults');
        if (array_key_exists($step, $apiresults)) {
            /* Set Form Errors manually  - get results from property mapper and add new errors */
            $result = $this->getControllerContext()->getRequest()->getOriginalRequestMappingResults();

            /* Add validation errors */
            foreach ($apiresults[$step] as $key => $value) {
                $error = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Validation\Error',
                    $apiresults[$step][$key], time());
                $result->forProperty($step . 'data.' . $key)->addError($error);
            }
            $this->getControllerContext()->getRequest()->setOriginalRequestMappingResults($result);
        }
    }

}
?>