# TYPO3 ViewHelper erstellen: So geht’s

TYPO3 ViewHelper werden eingesetzt, um wiederverwendbare Funktionen direkt in **Fluid-Templates** zu integrieren. So lassen sich komplexe Daten verarbeiten, Schleifen steuern und Bedingungen einfügen. Die Trennung von Logik und Präsentation macht den Code wartungsfreundlicher und optimiert die Performance.

## Was ist ein TYPO3 ViewHelper?

Ein TYPO3 ViewHelper ist eine Funktionalität innerhalb des TYPO3 CMS, die speziell für das Template-System **Fluid** entwickelt wurde. [TYPO3 Fluid](https://www.ionos.de/digitalguide/hosting/cms/typo3-fluid/) ist das Standard-Templating-System, mit dem sich das Layout und die Struktur einer Webseite definieren lassen. ViewHelper erweitern Fluid um benutzerdefinierte Funktionen, die es erlauben, komplexe logische Operationen durchzuführen.

Technisch gesehen handelt es sich bei einem ViewHelper um eine **PHP-Klasse**, die eine bestimmte Funktionalität kapselt. Diese Klasse kann dann in einem Fluid-Template durch spezielle Tags aufgerufen werden, die als ViewHelper-Tags bekannt sind. Ein ViewHelper kann eine Vielzahl von Aufgaben übernehmen, wie zum Beispiel die Formatierung von Daten, das Einfügen von Bedingungen, das Erstellen von Schleifen oder das Abrufen von Inhalten aus Datenbanken.

## Wofür benötigt man einen TYPO3 ViewHelper?

Ein zentraler Vorteil von ViewHelpern ist, dass sie die **Logik von der Präsentation trennen**. In modernen Webentwicklungspraktiken hat sich die Methode bewährt, die Datenverarbeitung oder -manipulation von der Darstellung zu separieren. Dadurch bleibt der Code übersichtlich, wartbar und skalierbar.

Ein weiterer wichtiger Vorteil von ViewHelpern ist ihre **Wiederverwendbarkeit**. Ein ViewHelper kann einmalig definiert und dann an beliebiger Stelle im Template oder sogar in mehreren Templates eingesetzt werden. Ist beispielsweise ein spezifisches Format für Datumsangaben erforderlich, kann ein ViewHelper einmal erstellt und dann in allen Templates eingesetzt werden.

Typische Anwendungsfälle für TYPO3 ViewHelper sind:

- **Datenformatierung:** Daten wie Datum, Zeit, Zahlen oder Währungen in das gewünschte Format bringen
- **Bedingungen und Schleifen:** Komplexe if-else-Abfragen oder Schleifen, die die Ausgabe des Templates steuern
- **Datenabfrage:** Daten aus einer Datenbank abrufen und sie im Template darstellen

## Welche Standard-ViewHelper gibt es?

Standard-ViewHelper sind die vordefinierten ViewHelper, die in TYPO3 Fluid direkt zur Verfügung stehen. Sie gehören zur **Standardbibliothek** von TYPO3 und bieten grundlegende Funktionalitäten, um Daten in Templates zu manipulieren, Schleifen und Bedingungen umzusetzen oder HTML-Elemente zu erzeugen. Die Standard-ViewHelper lassen sich in mehrere Kategorien einteilen.

### Steuerung von Logik (Control Structures)

Diese ViewHelper ermöglichen Bedingungen, Schleifen und Variablen-Handling:

- **`<f:if>`:** führt Inhalte basierend auf einer Bedingung aus
- **`<f:else>`:** alternative Inhalte für `<f:if>`
- **`<f:for>`:** iteriert über eine Liste oder ein Array
- **`<f:alias>`:** definiert Variablen für einen bestimmten Bereich

**Beispiel:**

```fluid
<f:if condition="{variable} == 1">
    <p>Variable is 1</p>
<f:else>
    <p>Variable is not 1</p>
</f:if>
```

### Datenmanipulation

Diese TYPO3 ViewHelper helfen, Werte oder Daten zu transformieren.

- **`<f:format.html>`:** konvertiert einen String in HTML
- **`<f:format.number>`:** formatiert eine Zahl
- **`<f:format.crop>`:** schneidet einen Text auf eine bestimmte Länge

**Beispiel:**

```fluid
<f:format.number decimals="2">{price}</f:format.number>
```

### Rendering und Layout

Es gibt ViewHelper, die das Rendering von Partials, Layouts und Sections steuern.

- **`<f:render>`:** rendert ein Partial oder eine Section
- **`<f:layout>`:** definiert das übergeordnete Layout eines Templates
- **`<f:section>`:** markiert einen benannten Block innerhalb eines Templates

**Beispiel:**

```fluid
<f:render partial="Product/Details" arguments="{product: product}" />
```

### Formulare und Eingabefelder

Dies dient zum Erzeugen von HTML-Formularen und Formularelementen.

- **`<f:form>`:** erzeugt ein Formular
- **`<f:form.textfield>`:** erstellt ein Textfeld
- **`<f:form.checkbox>`:** erstellt eine Checkbox

**Beispiel:**

```fluid
<f:form action="save">
    <f:form.textfield name="username" />
    <f:form.submit value="Save" />
</f:form>
```

### Content Output

Diese TYPO3 ViewHelper geben Inhalte oder Medien aus.

- **`<f:translate>`:** übersetzt einen Schlüssel in eine Sprache
- **`<f:debug>`:** gibt Debugging-Informationen aus
- **`<f:image>`:** rendert ein Bild mit optionaler Verarbeitung

**Beispiel:**

```fluid
<f:translate key="welcomeMessage" />
```

### ViewHelper `f:alias`

`f:alias` ist ebenfalls ein TYPO3 ViewHelper in Fluid. Er gehört zur Standardbibliothek der Fluid-ViewHelper und wird verwendet, um **Werte oder komplexe Ausdrücke in Variablen umzuwandeln**, die dann im Template referenziert werden können.

Der `f:alias`-ViewHelper erlaubt es Ihnen, eine oder mehrere Variablen zu definieren, die innerhalb eines bestimmten Bereichs im Template verfügbar sind. Er nimmt eine `map` als Attribut, in der Sie die Variablen und ihre Werte definieren. Die Variablen stehen nur innerhalb des Tags zur Verfügung, in dem der `f:alias` genutzt wird.

**Syntax:**

```fluid
<f:alias map="{variableName: value}">
    <!-- variable can be used here -->
</f:alias>
```

**Beispiel:**

```fluid
<f:alias map="{greeting: 'Hello, world!'}">
    <div>{greeting}</div>
</f:alias>
```

**Ausgabe:**

```html
<div>Hello, world!</div>
```

Der `f:alias`-ViewHelper kann auch für komplexere Logik verwendet werden, zum Beispiel um Ergebnisse eines anderen ViewHelpers zu speichern:

```fluid
<f:alias map="{userImage: f:image(src: 'user.jpg', treatIdAsReference: true)}">
    <img src="{userImage}" alt="User image">
</f:alias>
```

**Ausgabe:**

```html
<img src="path/to/user.jpg" alt="User image">
```

## Benutzerdefinierte TYPO3 ViewHelper: Anleitung zur Erstellung und Nutzung

TYPO3 bietet bereits eine Vielzahl von Standard-ViewHelpern, doch es gibt oft Szenarien, in denen benutzerdefinierte Anforderungen nicht durch diese Standardlösungen erfüllt werden können. In solchen Fällen ist es empfehlenswert, eigene ViewHelper zu entwickeln. Die Erstellung eines eigenen ViewHelpers erfolgt durch das Erstellen einer PHP-Klasse, die von `\TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper` erbt. Darin wird dann die gewünschte Logik umgesetzt.

Das Ziel dieses Tutorials ist die Erstellung eines benutzerdefinierten TYPO3 ViewHelpers, der es ermöglicht, automatisch ein Gravatar-Bild für eine E-Mail-Adresse anzuzeigen. Gravatar (Globally Recognized Avatar) ist ein weit verbreiteter Dienst, der mit einer E-Mail-Adresse verknüpfte Avatare bereitstellt. Durch diesen ViewHelper soll die Integration eines Gravatar-Bildes in Fluid-Templates so einfach wie möglich gestaltet werden.

### Einsatzbeispiel des ViewHelpers in einem Fluid-Template

Der Gravatar-ViewHelper wird folgendermaßen in einem Fluid-Template verwendet:

```fluid
<html
    xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
    xmlns:m="http://typo3.org/ns/MyVendor/MyExtension/ViewHelpers"
    data-namespace-typo3-fluid="true"
>
    <m:gravatar emailAddress="username@example.org" alt="Gravatar icon of user" />
</html>
```

Hierbei ist `m` ein Beispiel für den Namespace des benutzerdefinierten ViewHelpers. Das Präfix `m` gibt an, dass alle Elemente mit `m:` von den benutzerdefinierten ViewHelpern aus der Erweiterung `MyVendor.MyExtension` stammen. Mit diesem Ansatz kann der ViewHelper in beliebigen Templates eingesetzt werden, ohne dass redundanter Code geschrieben werden muss.

### Erstellung eines eigenen Fluid-ViewHelpers

Die Entwicklung eines benutzerdefinierten TYPO3 ViewHelpers erfordert die Erstellung einer PHP-Klasse, die von der Basisklasse `AbstractViewHelper` erbt. Diese Basisklasse bietet grundlegende Funktionalitäten, wie die Registrierung von Argumenten und die Implementierung der Renderlogik.

Der ViewHelper wird typischerweise in einer TYPO3-Erweiterung unter `Classes/ViewHelpers` abgelegt. Der Name der Datei sollte mit dem Namen des ViewHelpers übereinstimmen. Für unseren Gravatar-ViewHelper wird eine Datei namens `GravatarViewHelper.php` angelegt.

Hier ist der vollständige Code der Klasse:

```php
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\ViewHelpers;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
final class GravatarViewHelper extends AbstractViewHelper
{
    protected $escapeOutput = false;
    public function initializeArguments(): void
    {
        // registerArgument($name, $type, $description, $required, $defaultValue, $escape)
        $this->registerArgument(
            'emailAddress',
            'string',
            'The email address to resolve the gravatar for',
            true,
        );
        $this->registerArgument(
            'alt',
            'string',
            'The optional alt text for the image',
        );
    }
    public function render(): string
    {
        $emailAddress = $this->arguments['emailAddress'];
        $altText = $this->arguments['alt'] ?? '';
        // this is improved with the TagBasedViewHelper (see below)
        return sprintf(
            '<img src="https://www.gravatar.com/avatar/%s" alt="%s">',
            md5($emailAddress),
            htmlspecialchars($altText),
        );
    }
}
```

- **Namespace und Basisklasse:** Die Klasse befindet sich im Namespace `MyVendor\MyExtension\ViewHelpers`. Durch das Erben der `AbstractViewHelper`-Klasse können grundlegende Fluid-Funktionen wie die Argumentregistrierung und die Render-Logik genutzt werden.
- **`initializeArguments`:** Diese Methode dient dazu, die Argumente zu definieren, die der ViewHelper erwartet. Im Fall des Gravatar-ViewHelpers sind dies:
- **`emailAddress`:** Eine erforderliche E-Mail-Adresse, anhand derer das Gravatar-Bild generiert wird.
- **`alt`:** Ein optionaler Alternativtext, der im HTML-Tag für das Bild angegeben wird.
- **`registerArgument`:** Diese Methode definiert den Namen des Arguments (`emailAddress` oder `alt`), den Datentyp (`string` in beiden Fällen) und eine Beschreibung, die für Dokumentationszwecke verwendet wird, ob das Argument erforderlich ist oder nicht.
- **`render`:** Die render-Methode enthält die Kernlogik des ViewHelpers. Sie wird aufgerufen, wenn der ViewHelper im Template benutzt wird.
- **E-Mail-Hashing:** Die E-Mail-Adresse wird zuerst in Kleinbuchstaben umgewandelt und Leerzeichen werden entfernt. Anschließend wird ein MD5-Hash der bereinigten E-Mail-Adresse erstellt. Dies ist erforderlich, da Gravatar die Avatare anhand von MD5-Hashes der E-Mail-Adressen speichert.
- **Gravatar-URL-Erstellung:** Der MD5-Hash wird an die URL `https://www.gravatar.com/avatar/` angehängt, um die spezifische Avatar-Bildadresse zu generieren.
- **Rückgabe eines HTML-&lt;img&gt;-Tags:** Der ViewHelper gibt ein vollständiges HTML-Bild-Tag zurück. Dabei wird die Gravatar-URL als `src`-Attribut benutzt und der Alternativtext (falls angegeben) als `alt`-Attribut eingefügt. Der Text wird mit `htmlspecialchars` vor potenziellen XSS-Angriffen geschützt.

**Ein Beispiel:**

Wenn die E-Mail-Adresse `username@example.org lautet`, wird ihr MD5-Hash `b58996c504c5638798eb6b511e6f49af` berechnet. Die generierte URL lautet dann:

`https://www.gravatar.com/avatar/b58996c504c5638798eb6b511e6f49af`

**Das Resultat ist ein HTML-Tag:**

```html
<img src="https://www.gravatar.com/avatar/b58996c504c5638798eb6b511e6f49af" alt="Gravatar icon of user" />
```

Der einfache Gravatar-ViewHelper, der bislang vorgestellt wurde, erfüllt grundlegende Anforderungen, indem er die URL für ein Gravatar-Bild basierend auf einer E-Mail-Adresse generiert und als HTML-Tag zurückgibt. Dennoch gibt es Möglichkeiten, ihn weiter auszubauen, um zusätzliche Funktionen und eine bessere Flexibilität zu gewährleisten.

### Unterstützung für Bildgrößen

Gravatar bietet die Möglichkeit, die Größe der angezeigten Avatare durch einen **URL-Parameter** anzupassen. Um diese Funktion zu integrieren, kann der TYPO3 ViewHelper erweitert werden, sodass er ein Argument `size` akzeptiert. Dieses Argument wird an die Gravatar-URL angehängt und erlaubt es, die gewünschte Pixelgröße des Bildes festzulegen.

**Code-Anpassungen:**

In der Methode `initializeArguments` wird ein neues Argument hinzugefügt:

```php
$this->registerArgument('size', 'int', 'size of Gravatar image in pixels', false, 80);
```

Der Standardwert für die Bildgröße beträgt 80 Pixel. In der `render`-Methode wird dieses Argument verwendet, um die URL zu erweitern:

```php
$size = $this->arguments['size'];
$gravatarUrl .= "?s=" . intval($size);
```

Durch diese Ergänzung können Benutzerinnen und Benutzer die Größe des Bildes im Template wie folgt festlegen:

```fluid
<m:gravatar emailAddress="user@example.org" size="200" />
```

### Umgang mit Standardbildern

Sie können ein Standardbild auswählen, das angezeigt wird, wenn keine Gravatar-Informationen für eine E-Mail-Adresse vorhanden sind. Standardbilder können entweder über eine URL oder als vordefinierte Gravatar-Optionen wie `mp`, `identicon`, `wavatar`, `retro` oder `robohash` angegeben werden.

Um diese Funktionalität zu integrieren, wird ein weiteres Argument `defaultImage` hinzugefügt:

```php
$this->registerArgument('defaultImage', 'string', 'URL or Gravatar option for a standard image', false, 'mp');
```

Innerhalb der `render`-Methode wird das Argument verarbeitet:

```php
$defaultImage = $this->arguments['defaultImage'];
$gravatarUrl .= "&d=" . urlencode($defaultImage);
```

So können die Benutzerin oder der Benutzer ein Standardbild für Avatare angeben:

```fluid
<m:gravatar emailAddress="user@example.org" defaultImage="identicon" />
```

### Erweiterung um zusätzliche Parameter

Gravatar unterstützt weitere Parameter wie das Festlegen eines Ratings (`rating`) oder die Definition einer Abweichungskontrolle (`forceDefault`). Um den TYPO3 ViewHelper flexibler zu gestalten, können auch diese Optionen als Argumente hinzugefügt werden. Beispielsweise könnte ein `rating`-Argument registriert werden:

```php
$this->registerArgument('rating', 'string', 'Age rating of Gravatar image (g, pg, r, x)', false, 'g');
```

Die resultierende URL würde dann auch dieses Argument enthalten:

```php
$rating = $this->arguments['rating'];
$gravatarUrl .= "&r=" . urlencode($rating);
```

### Schutz vor Cross-Site-Scripting (XSS)

Um dafür zu sorgen, dass der generierte HTML-Code sicher ist, wird die Funktion `htmlspecialchars` eingesetzt, um Benutzer-Eingaben zu entschärfen. Dies verhindert, dass bösartige Skripte in das Template eingebettet werden können. Beispielsweise wird das `alt`-Attribut so behandelt:

```php
return sprintf('<img src="%s" alt="%s" />', $gravatarUrl, htmlspecialchars($alt));
```

### Validierung der Argumente

Eine gute Praxis besteht darin, Eingaben vor der Verarbeitung zu validieren. Zum Beispiel kann die Größe (`size`) auf einen sinnvollen Bereich eingeschränkt werden, um unvorhersehbares Verhalten zu vermeiden:

```php
$size = max(1, min(2048, intval($this→arguments['size'])));
```

Mit solchen Schutzmaßnahmen bleibt der TYPO3 ViewHelper robust gegenüber fehlerhaften oder potenziell schädlichen Eingaben.

### `compile()`-Methode

Die Methode `compile()` wird verwendet, um den ViewHelper für eine direkte PHP-Ausführung zu kompilieren. Sie eignet sich, wenn der ViewHelper lediglich eine Wrapper-Funktion für native PHP-Funktionen ist. Dies eliminiert die Notwendigkeit, den ViewHelper vollständig auszuführen und erhöht die Leistung.

Hier ist ein TYPO3 ViewHelper, der eine Zeichenkette in Kleinbuchstaben umwandelt:

```php
<?php
namespace MyVendor\BlogExample\ViewHelpers;
use TYPO3Fluid\Fluid\Core\Compiler\TemplateCompiler;
use TYPO3Fluid\Fluid\Core\Parser\SyntaxTree\ViewHelperNode;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
final class StrtolowerViewHelper extends AbstractViewHelper
{
    public function initializeArguments(): void
    {
        $this->registerArgument('string', 'string', 'The string to lowercase.', true);
    }
    public function compile(
        $argumentsName,
        $closureName,
        &$initializationPhpCode,
        ViewHelperNode $node,
        TemplateCompiler $compiler
    ): string {
        return sprintf("strtolower(%s['string'])", $argumentsName);
    }
}
```

### Migration von `renderStatic()`

Die Methode `renderStatic()` wurde in TYPO3 v12 und Fluid v2.15 als veraltet markiert. Sie wurde häufig zusammen mit den Traits `CompileWithRenderStatic` oder `CompileWithContentArgumentAndRender` verwendet. Die Migration auf `render()` ist notwendig, um mit der neuesten TYPO3-Version kompatibel zu sein.

**Vorher:**

```php
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext): string
{
    $emailAddress = $arguments['emailAddress'];
    return sprintf('<img src="https://www.gravatar.com/avatar/%s">', md5($emailAddress));
}
```

**Nachher:**

```php
public function render(): string
{
    $emailAddress = $this->arguments['emailAddress'];
    return sprintf('<img src="https://www.gravatar.com/avatar/%s">', md5($emailAddress));
}
```

### Entfernen von `CompileWithContentArgumentAndRenderStatic`

Falls der Trait `CompileWithContentArgumentAndRenderStatic` genutzt wurde, muss die Logik angepasst werden. Statt `renderChildrenClosure()` wird die Methode `$this->renderChildren()` eingesetzt.

**Vorher:**

```php
$emailAddress = $renderChildrenClosure();
```

**Nachher:**

```php
$emailAddress = $this→renderChildren();
```

### Ersatz von `renderStatic()`-Aufrufen

Falls ein TYPO3 ViewHelper einen anderen ViewHelper durch dessen `renderStatic()`-Methode aufgerufen hat, muss dies durch den Einsatz von `invoke()` angepasst werden.

**Vorher:**

```php
$gravatorUrl = GravatarUrlViewHelper::renderStatic(['email', $emailAddress], $renderChildrenClosure, $renderingContext);
```

**Nachher:**

```php
$gravatarUrl = $this->renderingContext->getViewHelperInvoker()->invoke(
    GravatarUrlViewHelper::class,
    ['email' => $emailAddress],
    $this->renderingContext,
    $this->renderChildren(),
);
```

[TYPO3 ist ein CMS mit großer Funktionsvielfalt](https://www.ionos.de/digitalguide/hosting/cms/typo3-ein-cms-mit-grosser-funktionsvielfalt/). Eine Anleitung zur [TYPO3-Installation](https://www.ionos.de/digitalguide/hosting/cms/typo3-installieren-anleitung/) und wie Sie eine [TYPO3-Webseite erstellen](https://www.ionos.de/digitalguide/websites/webseiten-erstellen/typo3-website-erstellen/) können, finden Sie in separaten Ratgebern.


This is a markdown version of: [https://www.ionos.de/digitalguide/hosting/cms/typo3-viewhelper/](https://www.ionos.de/digitalguide/hosting/cms/typo3-viewhelper/) for AI/LLM consumption.