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

Modul-Grundgerüst: registration.php, module.xml und Namespace-Konventionen

Modul-Grundgerüst: registration.php, module.xml und Namespace-Konventionen

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

Bevor Kapitel 3 die erste Tabelle entwirft, braucht es das Modul selbst: einen registrierten Namespace, den Magento beim Start erkennt. Dieses Kapitel legt Mironsoft\Loyalty an und erklärt die Namenskonventionen, an die sich alle folgenden 105 Kapitel halten.

Namespace und Modulname

Der PHP-Namespace ist Mironsoft\Loyalty, der Magento-Modulname (mit Unterstrich statt Backslash, wie in module.xml und registration.php verlangt) ist Mironsoft_Loyalty. Der Modulordner liegt unter app/code/Mironsoft/Loyalty/ - Vendor- und Modulname bilden direkt die ersten beiden Verzeichnisebenen, PSR-4-konform.

Storefront-URLs bekommen später (Block 6) einen eigenen Front Name: treuepraemien auf der deutschen und rewards auf der englischen Store-View. Das ist an dieser Stelle nur eine Randnotiz - der Router selbst entsteht erst in Kapitel 46, sobald es tatsächlich Controller gibt, die er ansteuern kann.

Zielstruktur nach Block 1

Die folgende Übersicht zeigt, wie das Modul aussieht, sobald alle neun Kapitel dieses Blocks abgeschlossen sind. Die einzelnen Dateien entstehen nach und nach in den Kapiteln 3 bis 9 - spätere Blöcke ergänzen weitere Verzeichnisse (Model/Reward/, Observer/, Cron/, Controller/ und so weiter), ohne etwas aus Block 1 zu verändern.

Mironsoft\Loyalty nach Block 1 (Kapitel 1-9)

app/code/Mironsoft/Loyalty/
├── registration.php
├── composer.json
├── etc/
│   ├── module.xml
│   ├── di.xml
│   ├── acl.xml
│   ├── cache.xml
│   ├── config.xml
│   └── adminhtml/
│       └── system.xml
├── Api/
│   ├── PointsLedgerRepositoryInterface.php
│   └── Data/
│       └── PointsLedgerInterface.php
├── Model/
│   ├── PointsLedger.php
│   ├── PointsLedgerRepository.php
│   ├── Cache/
│   │   └── Type/
│   │       └── LoyaltyCatalog.php
│   ├── Config/
│   │   └── LoyaltyConfig.php
│   ├── ResourceModel/
│   │   ├── PointsLedger.php
│   │   └── PointsLedger/
│   │       └── Collection.php
│   └── Service/
│       └── PointsCalculator.php
└── Console/
    └── Command/
        └── RecalculatePointsCommand.php

registration.php

Jedes Magento-2-Modul registriert sich selbst über ComponentRegistrar::register() - ohne diese Datei bleibt das Modul für Magento unsichtbar, egal was sonst im Ordner liegt.

app/code/Mironsoft/Loyalty/registration.php
<?php

declare(strict_types=1);

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,
    'Mironsoft_Loyalty',
    __DIR__
);

module.xml mit sequence

module.xml deklariert den Modulnamen und - wichtig für Kapitel 3 - eine <sequence>. Der Punkte-Ledger referenziert per Fremdschlüssel Tabellen aus Magento_Customer und Magento_Sales; damit setup:upgrade diese Tabellen garantiert schon angelegt hat, bevor db_schema.xml darauf verweist, müssen beide Module in der sequence stehen.

app/code/Mironsoft/Loyalty/etc/module.xml
<?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_Loyalty">
        <sequence>
            <module name="Magento_Customer"/>
            <module name="Magento_Sales"/>
        </sequence>
    </module>
</config>

Achtung: Eine fehlende sequence fällt nicht sofort auf: Auf einem Entwicklungssystem, auf dem Magento_Customer und Magento_Sales ohnehin schon installiert sind, funktioniert alles. Bei einer frischen Installation kann Magento die Modul-Reihenfolge dagegen anders wählen und db_schema.xml versucht, einen Fremdschlüssel auf eine noch nicht existierende Tabelle zu legen - setup:upgrade bricht dann mit einem SQL-Fehler ab.

Namenskonventionen für die restliche Serie

  • PHP-Klassen: immer declare(strict_types=1), Constructor Property Promotion für Dependency Injection, vollständiges PHPDoc auf jeder Klasse und jeder Methode.
  • Datenbanktabellen: mironsoft_loyalty_<entität>, zum Beispiel mironsoft_loyalty_points_ledger (Kapitel 3).
  • Konfigurationspfade: mironsoft_loyalty/<gruppe>/<feld>, zum Beispiel mironsoft_loyalty/general/points_per_euro (Kapitel 7).
  • ACL-Ressourcen: Mironsoft_Loyalty::<bereich>, konsistent mit den anderen Mironsoft-Modulen dieses Projekts.
  • addFieldToFilter() mit einem Integer-Wert wird immer als ['eq' => $value] geschrieben, nie als nackter Skalar - Kapitel 4 zeigt das an der ersten Collection.

Tipp: Diese Konventionen stammen direkt aus der Projekt-CLAUDE.md - sie gelten identisch für alle zwölf Blöcke dieser Serie, nicht nur für Block 1.

Mit registriertem Modul und korrekter sequence kann Kapitel 3 die erste Tabelle entwerfen.