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.

20. Nov 2013

Hilfe statt Geschenke

Gravatar: Thorge Larson

Aufgrund der Ereignisse auf den Philippinen haben wir uns dieses Jahr dazu entschlossen, auf die Präsente an unsere Kunden zum Jahresende zu verzichten und den gesamten dafür geplanten Betrag an die Opfer des Taifuns Haiyan auf den Philippinen zu spenden.

Hierfür haben unsere Mitarbeiter das Deutsche Rote Kreuz als Empfänger der Spende ausgewählt. Wir hoffen, damit den Opfern der Katastrophe etwas helfen zu können und sind uns sicher, auch im Interesse unserer Kunden und Partner zu handeln. Wenn Sie auch helfen möchten, können Sie direkt online spenden auf der extra eingerichteten Spendenseite des DRK.

23. Okt 2013

Fronteers 2013

Gravatar: Berit Hlubek
  • Fronteers-Location: Pathé Tuschinski von Außen
  • Fronteers-Location: Pathé Tuschinski von Innen

Die Fronteers Konferenz steht bereits seit einigen Jahren auf meiner Konferenz-Wunschliste, doch leider hatte sich diese in den letzten Jahren regelmäßig mit der TYPO3 Konferenz T3CON überschnitten. Als aktives Mitglied der TYPO3 Community und Mitarbeiterin einer TYPO3 Agentur hatte ich mich daher immer gegen die Fronteers entschieden. Dieses Jahr passte der Termin aber endlich und Christopher Hlubek und ich konnten die Konferenz zum ersten Mal besuchen.

Die Fronteers ist eine englisch-sprachige Konferenz fokussiert auf Frontend-Entwicklung und Web-Technologien, organisiert von dem gleichnamigen holländischen Verein. Bereits zum sechsten Mal fand sie dieses Jahr statt und wie immer im Pathé Tuschinsky, einem historischen Theater mitten in Amsterdam. Die Konferenz zeichnet sich nicht nur durch namhafte internationale Speaker aus, sondern ebenso durch ein ausgereiftes Konzept. Über beide Konferenztage werden die Teilnehmer (dieses Jahr ca. 550) durch den Ceremony Master durch die Veranstaltung geleitet. In diesem Jahr wurde diese Aufgabe von Paul Irish (Google Chrome Developer Advocate) übernommen. Neben der Begrüßung hat er jeden Speaker mit kurzer Beschreibung angekündigt und während der Vorträge alle auftretenden Fragen gesammelt (die Teilnehmer sollten über Twitter Fragen zum Talk posten). Als Abschluss jedes Talks gab es eine kurze Q&A Session in welcher Paul Irish die aufgekommenen Fragen zusammengefasst an den jeweiligen Speaker gerichtet hat. Ein aus meiner Sicht sehr gelungenes Konzept, bei welchem zum einen gesammelt alle relevanten Fragen geklärt werden und zum anderen die kurze Überbrückungszeit beim Wechsel der Speaker sinnvoll genutzt wird.

Im Folgenden gebe ich einen kurzen Überblick über einige Themen und Talks.

Performance

Eines der großen Themen der Konferenz war die Performance von Webseiten aus Frontend-Sicht. Paul Lewis (Google Chrome Developer Relations Team) hat hierzu einen Überblick gegeben, indem er gezeigt hat wie genau der Browser jeden Pixel einer Webseite rendert. So wurde zum Beispiel klar, dass das Ändern einer Klasse auf dem body-Tag ein komplettes Neu-Zeichnen der Webseite zur Folge hat, weil sich theoretisch jedes Element verändert haben könnte. Klassen sollten also immer möglichst dicht am zu verändernden Element gesetzt werden.

Auch bei Steve Souders‘ (Google Head Performance Engineer) Talk „Pre-Browsing“ ging es um das Thema Performance, allerdings von einem völlig anderen Gesichtspunkt ausgehend. Auf Basis der Rendering-Abfolge des Browsers (1. Prerender und Prefetch, 2. Transitions, 3. Preloading) ist er auf die verschiedenen Möglichkeiten eingegangen, wie ein Browser die Ressourcen einer Website möglichst schnell laden kann. Dazu gehört zum Beispiel das asynchrone Ausliefern von JavaScript, damit nicht das Laden der Webseite von den Skripten verzögert wird. In diesem Fall entfällt dann auch der Umweg Skripte im Footer einzubinden, anstatt im Header „Scripts in the bottom are so 2007 ;)“. Eine weitere Möglichkeit besteht darin neue Techniken wie Prerender und Prefetch zu nutzen. Darüber kann man den Browser zum Beispiel dazu bringen auf Seite X bereits Seite Y vorzuladen, wenn diese Seite zum Beispiel in den meisten Fällen als Folgeseite der Benutzer aufgerufen wird oder der Benutzer mit der Maus über einen Link hovert.

Frontend-Techniken der Zukunft

Natürlich ist ein Ziel einer Konferenz wie der Fronteers auch der Blick in die Zukunft. Hierzu hat Zoe Mickley Gillenwater (Web accessibility specialist at AT&T) einen Einblick in die aktualisierte Version der Flexbox-Eigenschaft gegeben.  Mit Flexbox können Layouts weitaus flexibler umgesetzt werden als mit Floatings. Das Besondere daran ist, dass darüber auch Einheiten gemischt werden können und Definitionen im Verhältnis zur Gesamtbreite möglich sind. Beispielsweise kann man ein Label neben einem Input-Feld ausrichten und dem Input-Feld über eine einfache Anweisung die Regel mitgeben, dass es die volle Restbreite neben dem Label einnehmen soll. Eine weitere Einsatzmöglichkeit betrifft die Ausrichtung der Höhe von nebeneinander positionierten Elementen. Bislang war es nur über JavaScript möglich zwei nebeneinander dargestellte Elemente, abhängig von deren Inhalten, in derselben Höhe darzustellen. Die Flexbox-Eigenschaft wird leider noch nicht von allen Browsern unterstützt, aber es ist denkbar dieses Feature als Optimierung für alle modernen Browser einzusetzen und für ältere Browser auf das verbesserte Layout zu verzichten (Progressive enhancement) oder per JavaScript nachzubilden.

Angelina Fabbro (Mozilla Firefox OS) hat einen Überblick über den aktuellen Status von Web Components gegeben. Mit der neuen HTML5 Technik ist es möglich HTML Elemente flexibel selber zu definieren und auszugeben.Die Spezifikation befindet sich derzeit noch in Entwicklung, einige Features lassen sich aber jetzt bereits über Polyfills nutzen (z.B. Google Polymer oder Mozilla X-Tag). In der Zukunft ergeben sich mit den Decorators von Templates neue Einsatzmöglichkeiten: für responsive Webseiten  ist es häufig erforderlich, dass Elemente in der mobilen Ansicht in einer anderen Reihenfolge dargestellt werden sollen als in der Desktop-Ansicht. Nicht immer ist dies einfach per CSS möglich, sondern erfordert JavaScript-Manipulationen des DOM. Über Web Components könnte die Darstellung ohne umfangreiche DOM-Manipulation durch CSS und Media Queries gelöst werden. 

Fronteers 2013: Harry Roberts Fazit

Design und Umsetzungsprozess bei modernen Projekten

In letzter Zeit hat sich das Tätigkeits-Feld eines typischen Frontend-Entwicklers stark verändert. Es geht schon lange nicht mehr nur darum ein Design pixelgenau umzusetzen. Mit dieser Thematik hat sich Harry Roberts (Senior UI Developer bei BSkyB) in seinem Talk auseinander gesetzt. So geht es bei der Umsetzung von Designs heute nicht mehr nur darum eine möglichst exakte Abbildung dessen umzusetzen, sondern über Kompromisse den besten Weg zwischen Design, Performance und Usability zu finden. Aber nicht jeder Designer ist glücklich damit, wenn sein Design nicht exakt umgesetzt wird. Eine Möglichkeit hierzu wäre, Designer und Frontend-Entwickler näher zusammen zu bringen und im Rahmen der Umsetzung gemeinsam die besten Wege zu finden.

Responsive Images

Die Anforderung Bilder für responsive Webseiten zu optimieren ist gar nicht mehr so neu, aber dennoch gibt es bislang keine ideale Lösung. Marcos Caceres (Mozilla API designer) ist unter anderem Lead Editor der <picture> Spezifikation innerhalb der „Responsive Images Community Group“ und hat einen Einblick in die bisherigen Lösungswege gegeben. Zusammenfassend kann gesagt werden, dass bisher keine Lösung alle Anforderung abdeckt und eine Standardisierung in Browsern dringend benötigt wird. Aus unserer Sicht ist der Vorschlag „src-N“ ein guter Ansatz im Vergleich zu den bisherigen Entwürfen und Spezifikationen. 

Typeface Design

Es gab gleich zwei gute Vorträge mit ausführlichem Einblick in das Thema Font Erstellung. Lucas de Groot (LucasFonts) ist wohl einer der bekanntesten Font-Designer. Er hat in seinem Talk eindrucksvoll gezeigt wie komplex das Erstellen eines guten Webfonts ist, der für alle Betriebssysteme und Bildschirmgrößen optimiert ist. Oliver Reichenstein (Founder of Information Architects) war als einer der Ersten davon überzeugt, dass eine Webseite mit Schriftgrößen um 12 Pixel nicht für das Lesen im Web geeignet ist und 16 Pixel völlig in Ordnung sind. Indem er den Leseabstand eines Buchs mit dem Abstand am Monitor verglichen hat, wurde klar, dass für die vergleichbar gute Lesequalität Schriftgrößen von 16 Pixel sehr passend sind. Zudem hat er gezeigt wie unterschiedlich ein Buchstaben in verschiedenen Schriftgrößen wirkt und worauf ein Font-Designer hier achten muss, damit die Schriftwirkung in verschiedenen Größen vergleichbar bleibt.

Fazit

Dies war nur ein kleiner Einblick in einen Teil der Fronteers Talks. Viele der Themen werden wir uns in der nächsten Zeit genauer anschauen und überall wo möglich in unsere tägliche Arbeit einfließen lassen. Es hat sich demnach definitiv gelohnt nach Amsterdam zu fahren und ich bin nächstes Jahr gerne wieder mit dabei.

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.