Zur Zeit wird gefiltert nach:TYPO3
Filter zurücksetzen

04. Apr 2014

Flexible Inhalte mit Fluid in TYPO3

Gravatar: Berit Hlubek
Berit HlubekKommentare 0

Letztes Jahr haben wir in unserem Blogeintrag Gridelements professionell nutzen die versionierbare Nutzung der Extension erklärt. Wir nutzen Gridelements überwiegend zur Realisierung verschachtelter Inhaltselemente. Für individuelle Inhalte mit vorgegebenen Eingabemöglichkeiten, zum Beispiel eine Teaser-Box, haben wir auf Basis eines kleinen PHP Helpers eine Fluid-Lösung entwickelt.

Ein großer Vorteil dieses Vorgehens ist die fast ausschließliche Verwendung von TYPO3 Core-Funktionen. Theoretisch wäre auch eine Nutzung des TypoScript Objekts FLUIDTEMPLATE möglich, wodurch der PHP Helper entfallen könnte.

Fluid Renderer

Der Fluid Renderer ist der PHP-Teil und wir haben diesen in Form einer dokumentierten Extension ins TER gestellt: Fluid FCE

Wir haben diesen entwickelt um ein paar erweiterte Funktionen zu nutzen und Flexform-Inhalte auszugeben. Zur Verwendung des Renderers ist ein kleines TypoScript-Snippet erforderlich:

  1. lib.fceRenderer = USER
  2. lib.fceRenderer {
  3. userFunc = Tx_MyExtKey_Content_FceRenderer->render
  4. extbase.pluginName = MyExtKey
  5. flexformFields = pi_flexform
  6. partialRootPath = EXT: my_ext_key/Resources/Private/Partials
  7. layoutRootPath = EXT: my_ext_key/Resources/Private/Layouts
  8. }

TsConfig

  1. mod.wizards.newContentElement.renderMode = tabs
  2. mod.wizards.newContentElement.wizardItems.common {
  3. elements.myextkey_teaserBox {
  4. icon = ../../../../typo3conf/ext/my_ext_key/Resources/Public/Icons/standard-fce.png
  5. title = Teaser Box
  6. description = Box mit Bild, Überschrift, Fließtext und optionalem Link
  7. tt_content_defValues {
  8. CType = myextkey_teaserBox
  9. }
  10. }
  11. show := addToList(myextkey_teaserBox)
  12. }

In diesem Fall wurde das FCE für das Projekt my_ext_key erstellt. Für jedes weitere FCE wird jeweils ein Block startend ab der Zeile elements.myextkey_teaserBox erstellt und innerhalb der letzten Zeile der zugehörige Key mit einem Komma getrennt in die runden Klammern eingefügt.

TypoScript-Definition des Inhalts-Elements

Zu jedem FCE gehört ein kleiner Schnippsel TypoScript, welcher dem Element das Basis-TypoScript für das Rendering über den PHP Helper zuweist und den Pfad des Fluid Templates definiert.

  1. tt_content.myextkey_teaserBox < lib.fceRenderer
  2. tt_content.myextkey_teaserBox {
  3. file = EXT: my_ext_key/Resources/Private/Templates/Elements/TeaserBox.html
  4. }

TCA-Konfiguration

Pro Inhaltselement muss in der ext_tables.php oder einer vergleichbaren Datei die TCA-Konfiguration der benötigen Datenbankfelder hinterlegt werden. Ohne die Nutzung von Flexforms kann das wie folgt aussehen:

  1. # Add backend element
  2. t3lib_extMgm::addPlugin(array('Teaser Box', 'my_ext_key'), 'CType');
  3.  
  4. # Configure fields for teaser box
  5. $TCA['tt_content']['types']['my_ext_key_teaserBox']['showitem'] = '
  6. --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.general;general,
  7. header;LLL:EXT:cms/locallang_ttc.xml:palette.header,
  8. bodytext;;9;richtext:rte_transform[flag=rte_enabled|mode=ts_css];,
  9. image,
  10. header_link,
  11. --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.appearance,
  12. --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.frames;frames,
  13. --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.access,
  14. --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.visibility;visibility,
  15. --palette--;LLL:EXT:cms/locallang_ttc.xml:palette.access;access,
  16. --div--;LLL:EXT:cms/locallang_ttc.xml:tabs.extended,
  17. tx_gridelements_container,
  18. tx_gridelements_columns,
  19. --div--;sys_language_uid,
  20. l18n_parent
  21. ';

Aufbau der Fluid-Templates

Für jedes FCE wird abschließend das passende Fluid-Template erstellt. Innerhalb des Templates kann auf jedes Feld zugegriffen werden, welches über das TCA definiert wurde.

Fluid Template

  1. <div class="box">
  2. <f:if condition="{header_link}">
  3. <f:then>
  4. <f:link.page parameter="{header_link}">
  5. <f:render partial="FluidContentElements/TeaserBox" arguments="{_all}" />
  6. </f:link.page>
  7. </f:then>
  8. <f:else>
  9. <f:render partial="FluidContentElements/TeaserBox" arguments="{_all}" />
  10. </f:else>
  11. </f:if>
  12. </div>

Fluid Partial

  1. <div class="box-content">
  2. <hgroup>
  3. <f:if condition="{header}">
  4. <h2><f:format.nl2br>{header}</f:format.nl2br></h2>
  5. </f:if>
  6. </hgroup>
  7. <f:if condition="{bodytext}">
  8. <f:format.html>{bodytext}</f:format.html>
  9. </f:if>
  10. </div>

Fazit

Für uns sind die Fluid FCEs zusammen mit der Nutzung der Extension gridelements eine ideale Kombination zum Aufbau von Webseiten die anspruchsvoll gestaltet aber dennoch redaktionell einfach zu pflegen sind.

Wir nutzen sie in jedem Projekt und haben bereits eine Sammlung an FCEs zusammen gestellt, die eine gute Basis bilden. Insbesondere die vollständige Versionierbarkeit stellt für uns einen großen Vorteil dar, denn sowohl für neue Projekte als auch für Deployment-Prozesse oder das Aufsetzen von Entwicklungs-Systemen fällt kein zusätzlicher Aufwand mehr an.

In einem zweiten Blog-Artikel werden wir auf die Nutzung von Flexforms und die Section/Container-Logik eingehen.

28. Feb 2014

Wir sind Premium Sponsor der T3DD14

Gravatar: Lars Lehners
T3DD14 Logo

Neben der T3CON sind die TYPO3 Developer Days DAS offizielle Event für Entwickler, Integratoren und alle, die sich im TYPO3 Kosmos umtreiben. Im Gegensatz zu einer herkömmlichen Konferenz geht es hier jedoch nicht nur um Input und Austausch, sondern insbesondere auch um die Weiterentwicklung der TYPO3 Produkte (TYPO3 CMS, TYPO3 Flow und TYPO3 Neos). 

Das offizielle Event der TYPO3 Association ist also irgendwo zwischen Codesprint und Konferenz angesiedelt. Entwickler und Integratoren haben hier die Möglichkeit, Ihr Wissen aufzustocken und sich mit anderen Menschen aus der Community auszutauschen. Darüber hinaus wird die Entwicklung der TYPO3 Produkte z.B. in Workshops aktiv vorangetrieben.

Das Schöne an dieser Veranstaltung: Man trifft auf viele bekannte Contributer, Extension Entwickler und anderen spannende Personen aus dem TYPO3 Umfeld. Hier hat jeder Interessierte die Möglichkeit, sich mit Community Mitgliedern auszutauschen, die man sonst nur aus Blog-Artikeln, Foren-Beiträgen oder offiziellen TYPO3 News kennt. Auf den DevDays trifft sich das „Who ist Who“ der TYPO3 Community, „Socialising“ ist dabei ein wesentlicher Aspekt dieses Events.

Die TYPO3 Developer Days sprechen übrigens nicht nur Entwickler und Integratoren an. Die Zielgruppe umfasst alle Menschen aus dem TYPO3 Umfeld! Designer, Anwender, Konzepter und andere sind ebenfalls herzlich dazu eingeladen an diesem Event teil zu nehmen. Das Themenspektrum ist breit gefächert und nach unserer Erfahrung lohnt sich der Besuch auch für „Nicht-Entwickler“.

In diesem Jahr finden die DevDays in Eindhoven in den Niederlanden statt. Waren es im letzten Jahr in Hamburg noch rund 200 Teilnehmer, so wurde in diesem Jahr bereits Platz für bis zu 400 TYPO3 Enthusiasten geschaffen. Als Premium Sponsor unterstützen wir die Umsetzung des Events aktiv und freuen uns auf spannende Talks, frische Ideen und tolle Begegnungen.

Die Tickets sowie die Möglichkeit, sich mit einem eigenen Thema für einen Talk anzumelden, gibt es auf der offiziellen T3DD14-Website.

networkteam ist Premium Sponsor der TYPO3 Developer Days 2014
26. Nov 2013

Release Party: Neos 1.0

Gravatar: Berit Hlubek
TYPO3 Neos Logo

Am 10. Dezember ist es so weit: Neos 1.0 wird veröffentlicht und wir möchten das feiern.

Ab 18 Uhr laden wir Euch auf Bier, Softdrinks und Pizza ein, um gemeinsam auf den Release anzustoßen. Gegen 18:30 werden wir den Live Stream aus Nürnberg starten, denn dann wird das Neos Team den Release veröffentlichen und anschließend eine Live Demo vorführen.

Der Fokus von TYPO3 Neos liegt auf guter Usability. Das intuitive Benutzer-Interface und In-Page-Editing ermöglichen Redakteuren eine möglichst einfache Bedienbarkeit. Änderungen an der Webseite können direkt in allen gewünschten Bildschirmbreiten kontrolliert werden. Das Neos Interface selber ist zudem auch für Touch-Geräte optimiert. So ist das Bearbeiten von Webprojekten zum Beispiel auch mit Tablets ohne Probleme möglich.

Egal mit welchem CMS ihr normalerweise arbeitet, jeder ist eingeladen mit uns den Release zu feiern und über Neos zu sprechen.

Hier noch einmal gesammelt alle Fakten:
18:00 - Start
18:30 - Live Stream von Release und Demo
Anschließend feiern wir den Release und diskutieren über Neos.

Ort: networkteam GmbH, Kleiner Kuhberg 42, 24103 Kiel

Zwecks Planung wäre es super, wenn ihr euch im offiziellen TYPO3 Wiki eintragen würdet oder uns kurz Bescheid gebt.

03. Sep 2013

Extension für mobile.de-Schnittstelle

Gravatar: Christian Lange
Standard mobile.de Händlerseite
Standard mobile.de Händlerseite mit festem Layout

Immer mehr unserer Kunden aus der Automobil- / Kfz-Branche fragen uns nach Lösungsmöglichkeiten zur Darstellung und Einbindung von Fahrzeugen in deren Internetseiten. Für solche Anwendungsfälle entwickeln wir normalerweise individuelle Lösungen, bei denen die Pflege und Datenhaltung direkt in TYPO3 erfolgt. Basierend auf diesen Daten werden passende Listen- und Detailansichten ausgeliefert. Solche individuellen Erweiterungen können mit Schnittstellen flexibel an die internen Systeme angebunden werden, wodurch eine zusätzliche manuelle Pflege der Datensätze entfallen kann.

Solche Schnittstellen müssen immer individuell auf die Spezifikationen des eingesetzten Verwaltungssystems angepasst werden und erzeugen hierdurch zusätzliche Aufwände. Bei unseren Kunden konnten wir als Gemeinsamkeit feststellen, dass obwohl unterschiedliche Systeme eingesetzt und darüber verschiedene Online-Fahrzeugbörsen bedient werden, die Fahrzeuge früher oder später in 99% aller Fälle zu mobile.de exportiert werden.

Somit lag es für uns auf der Hand nach einer praktikablen Lösung zu suchen, mobile.de als zentrale Schnittstelle zu verwenden und dadurch weiterhin unabhängig von der intern eingesetzten Software zu sein. Glücklicherweise bietet die Automobil-Plattform eine sehr gute Export-Schnittstelle über welche die gepflegten Fahrzeuge eines Händlers, wie Lager- / Gebrauchtwagen, für die weitere Verwendung abgerufen werden können - Sogar für Motorräder und LKW kann diese Schnittstelle genutzt werden.

Auf Basis von Extbase und Fluid haben wir eine Erweiterung (Extension) für TYPO3 entwickelt, die diese mobile.de-Schnittstelle nutzt und die Fahrzeuge - bei Bedarf auch von mehreren Händler-Accounts - abruft, zusammen fasst und je nach Wunsch auf der Webseite darstellt. Im Gegensatz zu der einfachen iFrame-Lösung die von mobile.de im Händlerbereich angeboten wird und einfach einzurichten ist, hat man mit unserer TYPO3-Extension die Möglichkeit das Layout & Design komplett flexibel an den Rest der Webseite anzupassen. Die angezeigten Werte und Filter lassen sich individuell bestimmen und positionieren. Durch den Einsatz von responsiven Templates lassen sich sämtliche Ansichten auch für Smartphones, Tablets und weitere Geräten optimiert ausgeben. Unerwünschte Werte wie z.B. die Gesamtanzahl der Fahrzeuge können dabei weggelassen werden und die komplexen Filtermöglichkeiten kann man auf eine jeweils sinnvolle Auswahl reduzieren. Bei Bedarf können die Fahrzeugdatensätze in TYPO3 durch eigene, nicht bereits durch mobile.de zur Verfügung gestellte, Werte / Informationen erweitert werden, so dass durch den externen Dienstleister hier keine Einschränkung geschaffen wird.

Screenshots vom TYPO3-Backend

Backend-Plugin für Listenansicht
Backend-Plugin für Listenansicht
Filterung über Schnittstelle
Filterung über Schnittstelle
Backend-Plugin Teaserbox
Backend-Plugin Teaserbox

Die Extension bringt bereits verschiedene Plugins mit einer Vielzahl an Einstellungsmöglichkeiten mit sich, so dass neben einer umfassenden Fahrzeugauflistung mit Filter- und Sortierungsmöglichkeit auch vordefinierte Listen ausgegeben werden können, um z.B. auf den Unterseiten bei einem Mehrmarkenbetrieb zu einem Fahrzeughersteller direkt die passenden Gebrauchtwagen zu dieser Marke anzeigen zu lassen. Modell-Detailseiten können automatisch mit passenden Gebraucht- / Lagerwagen angereichert werden, so dass ein Interessent direkt sehen kann, was der Händler vorrätig hat. Schließlich ist dies einer der Hauptunterschiede zu den Mitbewerbern.

Zusätzlich zu diesen Listenansichten besteht die Möglichkeit ausgewählte Fahrzeuge in sogenannten Teaser-Boxen anzupreisen. Darüber lässt sich z.B. das „Fahrzeug des Monats“ zu einem besonders interessanten Preis an präsenten Stellen der Website darstellen.

Durch die Darstellung der Detailseiten direkt innerhalb der eigenen Webseite kann nicht nur deren Darstellung auf die eigenen Bedürfnisse angepasst werden, sondern der Inhalt kann von Suchmaschinen auf der Seite gefunden werden und steigert dadurch die Sichtbarkeit der Internetseite in Google & Co. Die Fahrzeuge lassen sich somit über feststehende URLs unterhalb der eigenen Domain direkt aufrufen. Für diese URLs kann man z.B. QRCodes erstellen, die dann direkt im Fenster des jeweiligen Fahrzeugs positioniert werden und dem Interessent direkt vor Ort weitere Informationen zur Verfügung stellen können.

Nicht nur auf der eigenen Webseite kann mit Hilfe unserer Erweiterung das Fahrzeugangebot präsentiert werden. Über TYPO3 lassen sich damit auch spezielle Ansichten generieren, die losgelöst von der eigentlichen Webpräsenz als Facebook App oder im iFrame innerhalb einer anderen Applikation anzeigt werden können. Der Vorteil gegenüber der von mobile.de zur Verfügung gestellten Facebook App ist dabei, dass auch dort das eigene Look & Feel eingehalten werden kann und außerdem mehrere Händler-Accounts (z.B. von unterschiedlichen Standorten / Marken) zusammengefasst angezeigt werden können, was ansonsten nicht möglich wäre.

Sollten wir jetzt Ihr Interesse geweckt haben, zögern Sie nicht uns direkt anzusprechen. Gemeinsam finden wir für Sie die optimale Lösung, um Ihre Gebraucht- und Lagerwagen auf Ihrer Webseite anzuzeigen.

28. Aug 2013

Verwendung von Custom Views in Flow

Gravatar: Kai Möller geb. Lassen
Kai Möller geb. LassenKommentare 0

Aufgabe: Ausgabe von Daten in verschiedenen Views (Fluid Template / JSON) unter Verwendung der selben Action-Methode.

Beispiel: Nehmen wir einmal an, wir haben eine Liste von Artikeln. Jeder Artikel beinhaltet neben Titel und Beschreibung auch ein Bild, welches als Thumbnail in einer bestimmten Größe ausgegeben werden soll. Die Darstellung soll sowohl in HTML (Fluid TemplateView) als auch in JSON (Flow JsonView) erfolgen.

Für die Darstellung des Fluid TemplateView geht man wie gewohnt vor. Innerhalb der Action-Methode werden Variablen definiert und an das Template weitergegeben. Im Template erfolgt dann die Formatierung mittels HTML. Das Rendering der Thumbnails in der passenden Größe kann über den ImageViewHelper des TYPO3.Media Package erreicht werden.

Für die Darstellung des JSON gibt es zwei Herangehensweisen: Entweder der JsonView wird innerhalb der Action-Methode konfiguriert (Flow JsonView) oder man verwendet einen CustomView und definiert dort wie das JSON aussehen soll. 

Der Nachteil bei der Verwendung des Flow JsonView ist, dass View-spezifische Aufgaben im Controller verbleiben und dieser dadurch schnell unübersichtlich wird.
In unserem Beispiel werden z.B. Thumbnails mit einer bestimmten Größe aus den im Artikel hinterlegten Bildern erstellt und ihre Url an den JsonView übergeben. Dies ist eigentlich eine Aufgabe, die vom View erledigt werden sollte.

Die Action-Methoden sowie die beiden Views unter Verwendung des Flow JsonView sehen folgendermaßen aus (siehe dazu auch den Abschnitt zu Json View in der Flow Dokumentation):

ArticleController unter Verwendung des JsonView

  1. namespace Networkteam\Blogexample\Controller;
  2.  
  3. class ArticleController extends \TYPO3\Flow\Mvc\Controller\ActionController {
  4.  
  5. /**
  6. * @Flow\Inject
  7. * @var \Networkteam\Blogexample\Domain\Repository\ArticleRepository
  8. */
  9. protected $articleRepository;
  10.  
  11. /**
  12. * @var \TYPO3\Flow\Resource\Publishing\ResourcePublisher
  13. * @Flow\Inject
  14. */
  15. protected $resourcePublisher;
  16.  
  17. /**
  18. * @var array
  19. */
  20. protected $viewFormatToObjectNameMap = array('json' => 'TYPO3\Flow\Mvc\View\JsonView');
  21.  
  22. /**
  23. * list articles for json and html
  24. */
  25. public function indexAction() {
  26. $format = $this->getControllerContext()->getRequest()->getFormat();
  27. $articles = $this->articleRepository->findAll();
  28.  
  29. switch ($format) {
  30. case 'json':
  31. // set urls for image thumbnails of each article
  32. foreach($articles as $article) {
  33. $imgUrl = '';
  34. $imgMaxWidth = $imgMaxHeight = 150;
  35. $articleImage = $article->getImage();
  36.  
  37. // scale image to given maxWith and maxHeight and resulting ratio
  38. if ($articleImage) {
  39. $imgWidth = $articleImage->getWidth() > $imgMaxWidth ? $imgMaxWidth : $articleImage->getWidth();
  40. $imgHeight = $imgWidth * ($imgMaxHeight / $imgMaxWidth);
  41. $imgUrl = $this->resourcePublisher->getPersistentResourceWebUri($articleImage->getThumbnail($imgWidth, $imgHeight, $articleImage::RATIOMODE_OUTBOUND)->getResource());
  42. }
  43.  
  44. $customArticles[] = array(
  45. 'title' => $article->getTitle(),
  46. 'date' => $article->getDate(),
  47. 'author' => $article->getAuthor(),
  48. 'content' => $article->getContent(),
  49. 'image' => $articleImage,
  50. 'imgUrl' => $imgUrl
  51. );
  52. }
  53.  
  54. // set vars for use in json view
  55. $this->view->assignMultiple(array(
  56. 'changed' => FALSE,
  57. 'timestamp' => time(),
  58. 'articles' => $customArticles
  59. ));
  60.  
  61. // set variables to render. By default only the variable 'value' will be rendered
  62. $this->view->setVariablesToRender(array('changed', 'timestamp', 'articles'));
  63.  
  64. // configure the json view
  65. $this->view->setConfiguration(array(
  66. 'articles' => array(
  67. '_descendAll' => array(
  68. '_exclude' => array('image')
  69. )
  70. )
  71. ));
  72. break;
  73.  
  74. case 'html':
  75. // configure the html view here
  76. $this->view->assign('articles', $articles);
  77. break;
  78. }
  79. }
  80. }

Resources/Private/Templates/Article/Index.html

  1. {namespace m=TYPO3\Media\ViewHelpers}
  2.  
  3. <f:layout name="Default" />
  4.  
  5. <f:section name="Title">Index view of Article controller</f:section>
  6.  
  7. <f:section name="Content">
  8. <h1>List of articles</h1>
  9. <p>Some data set by the controller:</p>
  10. <f:for each="{articles}" as="article">
  11. <dt>Title:</dt>
  12. <dd>{article.title}</dd>
  13.  
  14. <dt>Date:</dt>
  15. <dd><f:format.date format="d.m.Y - H:i:s">{article.date}</f:format.date></dd>
  16.  
  17. <dt>Author:</dt>
  18. <dd>{article.author}</dd>
  19.  
  20. <dt>Content:</dt>
  21. <dd>{article.content}</dd>
  22.  
  23. <f:if condition="{article.image}">
  24. <dt>Image:</dt>
  25. <dd><m:image image="{article.image}" maximumWidth="150" alt="{article.image.title}" /></dd>
  26. </f:if>
  27. </dl>
  28. </li>
  29. </f:for>
  30. </ul>
  31. </f:section>

Der Custom View

Man sieht sehr deutlich, wie viel Code bereits in der Action-Methode steckt. Schöner geht es mit einem CustomView. Ähnlich wie beim Fluid TemplateView und JsonView können Packages eigene Views mitbringen. Der Action-Controller kann über die Instanzvariablen $defaultViewObjectName und $viewFormatToObjectNameMap so konfiguriert werden, dass er für bestimmte Formate eigene Views verwendet (Man sehe sich hierzu die Klasse \TYPO3\Flow\Mvc\Controller\ActionController genauer an).

Die eigenen Views werden im Ordner "View/ControllerName/" des Application Package abgelegt (siehe auch TYPO3 Flow Ordner Struktur).

Der Name des CustomView besteht immer aus dem Namen der Action und dem MIME-MediaType. In unserem Beispiel sieht das folgendermaßen aus:
Der ArticleController beinhaltet die customAction() Methode. Der MIME Type soll JSON sein. Der resultierende Klassennamen der CustomView ist damit CustomJson.

Soll das Ausgabeformat reiner Text sein (MIME Type TXT), müsste die View-Klasse CustomTxt heißen. Grundlage für die Namenskonvention ist der MIME MediaType. Die unterstützen Formate können in der Klasse \TYPO3\Flow\Utility\MediaTypes nachgelesen werden.

Der Vorteil bei der Verwendung des CustomView ist, dass die Action-Methode sehr sauber und übersichtlich bleibt. Alle View-spezifischen Aufgaben verbleiben im jeweiligen View.

Der Aufbau eines CustomView gestaltet sich folgendermaßen: Die View Klasse leitet von \TYPO3\Flow\Mvc\View\AbstractView ab welche wiederum das \TYPO3\Flow\Mvc\View\ViewInterface implementiert. Daher muss nur die render() Methode für den CustomView implementiert werden.

Innerhalb der render() Methode kann nun die JSON-Ausgabe als String zusammengebaut und zurückgegeben werden. Dabei stehen beispielsweise in $this->variables alle Variablen zur Verfügung, welche in der Action-Methode mit $this->view->assign() zugewiesen wurden. Des Weiteren kann auf den ControllerContext zugegriffen werden, über welchen unter anderem der Content-Type Header gesetzt werden kann.

Ebenfalls erfolgt die Generierung der Thumbnail-Url innerhalb des Views (siehe Methode articleToArray()).

Somit gestaltet sich die Action-Methode sehr sauber und aufgeräumt und die Formatierung von HTML und JSON kann einfach in den jeweiligen Views erfolgen.

ArticleController unter Verwendung des CustomView

  1. namespace Networkteam\Blogexample\Controller;
  2.  
  3. class ArticleController extends \TYPO3\Flow\Mvc\Controller\ActionController {
  4.  
  5. /**
  6. * @Flow\Inject
  7. * @var \Networkteam\Blogexample\Domain\Repository\ArticleRepository
  8. */
  9. protected $articleRepository;
  10.  
  11. /**
  12. * list articles
  13. */
  14. public function customAction() {
  15. $articles = $this->articleRepository->findAll();
  16. $this->view->assign('articles', $articles);
  17. }
  18. }

View/Article/CustomJson.php

  1. namespace Networkteam\Blogexample\View\Article;
  2.  
  3. class CustomJson extends \TYPO3\Flow\Mvc\View\AbstractView {
  4.  
  5. /**
  6. * @var \TYPO3\Flow\Resource\Publishing\ResourcePublisher
  7. * @Flow\Inject
  8. */
  9. protected $resourcePublisher;
  10.  
  11. /**
  12. * @return string
  13. */
  14. public function render() {
  15. $data = array(
  16. 'changed' => FALSE,
  17. 'timestamp' => time(),
  18. 'articles' => array()
  19. );
  20.  
  21. # set Content-Type
  22. $this->controllerContext->getResponse()->setHeader('Content-Type', 'application/json');
  23.  
  24. # get variables form controller action
  25. $articles = $this->variables['articles'];
  26.  
  27. foreach($articles as $article) {
  28. $data['articles'][] = $this->articleToArray($article, 150, 150);
  29. }
  30.  
  31. return json_encode($data);
  32. }
  33.  
  34. /**
  35. * @param \Networkteam\Blogexample\Domain\Model\Article $article
  36. * @param integer $imgMaxWidth
  37. * @param integer $imgMaxHeight
  38. * return array
  39. */
  40. protected function articleToArray(\Networkteam\Blogexample\Domain\Model\Article $article, $imgMaxWidth = NULL, $imgMaxHeight = NULL) {
  41. $imgUrl = '';
  42. $articleImage = $article->getImage();
  43.  
  44. // scale image to given maxWith and maxHeight and resulting ratio
  45. if ($articleImage) {
  46. $imgWidth = $articleImage->getWidth() > $imgMaxWidth ? $imgMaxWidth : $articleImage->getWidth();
  47. $imgHeight = $imgWidth * ($imgMaxHeight / $imgMaxWidth);
  48. $imgUrl = $this->resourcePublisher->getPersistentResourceWebUri($articleImage->getThumbnail($imgWidth, $imgHeight, $articleImage::RATIOMODE_OUTBOUND)->getResource());
  49. }
  50.  
  51. return array(
  52. 'title' => $article->getTitle(),
  53. 'date' => $article->getDate(),
  54. 'author' => $article->getAuthor(),
  55. 'content' => $article->getContent(),
  56. 'imgUrl' => $imgUrl
  57. );
  58. }
  59. }

Routing

Wie wird nun aber bei Aufruf der indexAction() bzw. customAction() festgelegt welcher View gerendert werden soll?

Über den @format Parameter der einzelnen Routen wird festgelegt welcher View für das Rendering der Route zuständig ist.

Dadurch, dass die Klasse View\Article\CustomJson.php vorhanden ist, wird für die customAction-Route mit @format = json dieser CustomView verwendet.

Bei der indexAction-Route mit @format = json ist innerhalb des ArticleController definiert welcher View für das Format zuständig ist: $viewFormatToObjectNameMap = array('json' => 'TYPO3\Flow\Mvc\View\JsonView');

Für beide Routen mit @format = html wird ein TYPO3\Fluid\View\TemplateView verwendet, da dies der Default ist (siehe $defaultViewObjectName in TYPO3\Flow\Mvc\Controller\ActionController).

Configuration/Routes.yaml

  1. -
  2. name: 'Article list'
  3. uriPattern: 'blogexample/articles.{@format}'
  4. defaults:
  5. '@package': 'Networkteam.Blogexample'
  6. '@controller': 'Article'
  7. '@action': 'index'
  8. '@format': 'html'
  9.  
  10. -
  11. name: 'Article list with custom view'
  12. uriPattern: 'blogexample/custom/articles.{@format}'
  13. defaults:
  14. '@package': 'Networkteam.Blogexample'
  15. '@controller': 'Article'
  16. '@action': 'custom'
  17. '@format': 'html'

Beispiel Package auf GitHub

Der gesamte Code des Artikels ist noch einmal als Beispiel im folgenden Package auf Github zu finden:

https://github.com/networkteam/Networkteam.Blogexample

Fazit:

Mit CustomViews kann in TYPO3 Flow der Controller aufgeräumt werden und Logik für den View in eigene PHP-Klassen ausgelagert werden. Das sorgt für eine bessere Erweiterbarkeit  und einfachere Wartung in der Zukunft.