Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

ViewModel für die Team-Daten schreiben

ViewModel für die Team-Daten schreiben

~7 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026

Jetzt bekommt die Team-Seite ihre eigentlichen Daten. Wie in Kapitel 7 besprochen, übernimmt das ein ViewModel, das ArgumentInterface implementiert - keine eigene Block-Klasse.

Die Datenstruktur

Jedes Team-Mitglied bekommt einen Namen, eine Rolle und eine Kategorie. Die Kategorie ist später der Schlüssel für die Alpine-Filterlogik (Kapitel 21) - deshalb nutzen wir dafür kurze, technische Bezeichner statt der Anzeige-Texte direkt.

app/code/Mironsoft/TeamPage/ViewModel/TeamMembers.php
<?php

declare(strict_types=1);

namespace Mironsoft\TeamPage\ViewModel;

use Magento\Framework\View\Element\Block\ArgumentInterface;

/**
 * Supplies team members and categories for the team page.
 *
 * The data is deliberately hard-coded for this tutorial - a real project
 * would inject a repository here instead.
 */
class TeamMembers implements ArgumentInterface
{
    /**
     * Returns all team members.
     *
     * @return array<int, array{name: string, role: string, category: string, photo: string}>
     */
    public function getTeamMembers(): array
    {
        return [
            ['name' => 'Anna Keller', 'role' => 'Backend-Entwicklerin', 'category' => 'entwicklung', 'photo' => 'anna.jpg'],
            ['name' => 'Ben Vogel', 'role' => 'UI/UX-Designer', 'category' => 'design', 'photo' => 'ben.jpg'],
            ['name' => 'Carla Roth', 'role' => 'Kundensupport', 'category' => 'support', 'photo' => 'carla.jpg'],
            ['name' => 'David Neumann', 'role' => 'Frontend-Entwickler', 'category' => 'entwicklung', 'photo' => 'david.jpg'],
        ];
    }

    /**
     * Returns all available categories, including "all", for the filter.
     *
     * @return array<int, array{key: string, label: string}>
     */
    public function getCategories(): array
    {
        return [
            ['key' => 'alle', 'label' => 'Alle'],
            ['key' => 'entwicklung', 'label' => 'Entwicklung'],
            ['key' => 'design', 'label' => 'Design'],
            ['key' => 'support', 'label' => 'Support'],
        ];
    }
}

Warum eine eigene getCategories()-Methode?

Man könnte die Kategorien theoretisch auch aus getTeamMembers() ableiten (array_unique über die category-Werte). Eine eigene Methode ist hier bewusst besser: Sie erlaubt eine feste Reihenfolge, einen sprechenden Anzeige-Text (label) getrennt vom technischen Schlüssel (key), und einen "Alle"-Eintrag, der in den eigentlichen Team-Daten gar nicht vorkommt.

Das ViewModel im Layout-XML binden

Jetzt wird das leere Layout-Handle aus Kapitel 18 um das ViewModel-Argument ergänzt:

app/code/Mironsoft/TeamPage/view/frontend/layout/team_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
            <block class="Magento\Framework\View\Element\Template"
                   name="team.page"
                   template="Mironsoft_TeamPage::team/index.phtml">
                <arguments>
                    <argument name="team_view_model" xsi:type="object">Mironsoft\TeamPage\ViewModel\TeamMembers</argument>
                </arguments>
            </block>
        </referenceContainer>
    </body>
</page>

Der Argument-Name team_view_model ist frei gewählt, muss aber exakt so im Template (Kapitel 20) wieder abgerufen werden.

Tipp: PHPStan (Level 5, siehe CLAUDE.md-Konventionen dieses Projekts) prüft unter anderem, ob Array-Rückgabetypen konsistent zur @return-Annotation sind. Bei Arrays mit fester Struktur wie hier lohnt sich die ausführliche Shape-Annotation (array{name: string, role: string, ...}) statt nur array - das gibt auch der IDE-Autovervollständigung im Template mehr Informationen.