Layout-XML und Controller für die neue Seite anlegen
Layout-XML und Controller für die neue Seite anlegen
~8 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
In diesem Kapitel bringen wir die Team-Seite zum ersten Mal überhaupt zum Laufen - noch ohne echten Inhalt, aber unter der Ziel-URL /team erreichbar. Dafür braucht es vier Dateien: Modul-Registrierung, Route, Controller und (leeres) Layout-XML.
Modul-Grundgerüst
<?php
declare(strict_types=1);
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Mironsoft_TeamPage',
__DIR__
);<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Mironsoft_TeamPage" setup_version="1.0.0">
<sequence>
<module name="Magento_Theme"/>
</sequence>
</module>
</config>Die Route: routes.xml
etc/frontend/routes.xml meldet den Front-Name team für das Frontend an und verbindet ihn mit unserem Modul:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route id="team" frontName="team">
<module name="Mironsoft_TeamPage"/>
</route>
</router>
</config>Der Controller: Controller/Index/Index.php
Der Ordnername Index unter Controller/ entspricht dem URL-Segment nach dem Front-Name, der Klassenname Index der Action - zusammen ergibt das /team/index/index, das Magento automatisch zu /team kürzt (Standard-Controller/Standard-Action). Der Controller nutzt Constructor Property Promotion und liefert nur die Seite aus - Daten kommen später über das ViewModel, nicht über den Controller selbst:
<?php
declare(strict_types=1);
namespace Mironsoft\TeamPage\Controller\Index;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Page;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
/**
* Serves the team overview page at /team.
*/
class Index implements HttpGetActionInterface
{
/**
* @param ResultFactory $resultFactory Creates the page result for the team page.
*/
public function __construct(
private readonly ResultFactory $resultFactory,
) {
}
/**
* Renders the team page via the team_index_index layout handle.
*
* @return ResultInterface|ResponseInterface
*/
public function execute(): ResultInterface|ResponseInterface
{
/** @var Page $resultPage */
$resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
$resultPage->getConfig()->getTitle()->set('Unser Team');
return $resultPage;
}
}HttpGetActionInterface statt der älteren, allgemeineren Action-Basisklasse macht explizit, dass dieser Controller nur GET-Requests bedient - für eine reine Anzeige-Seite ohne Formular-Submit die richtige Wahl.
Ein erstes, leeres Layout-Handle
Damit die Seite überhaupt eine gültige Antwort liefert (statt eines leeren Standard-Layouts), legen wir schon jetzt das Layout-Handle an - vorerst mit einem einfachen Platzhalter-Block, den wir in Kapitel 20 durch das echte Template ersetzen:
<?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"/>
</referenceContainer>
</body>
</page>Modul aktivieren und testen
bin/magento module:enable Mironsoft_TeamPage
bin/magento setup:upgrade
bin/cache-cleanAchtung: An dieser Stelle existiert das Template team/index.phtml noch nicht (das kommt erst in Kapitel 20) - ein Aufruf von /team würde also einen Fehler "Template file ... does not exist" auswerfen. Das ist an dieser Stelle erwartet; Kapitel 19 und 20 schließen diese Lücke.