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.
<?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:
<?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.