Startfertige Website-Vorlage, die den Mähbarkeitsindex (MFI) auf einer eigenen Seite darstellt. Sie holt Wetterdaten, lässt daraus über die MFI-API den Indexwert berechnen, speichert das Ergebnis in MySQL und zeigt es im Standard-MFI-Schema an.
Gedacht als Ausgangspunkt für eigene Projekte: hochladen, Assistent durchlaufen, fertig.
Dort läuft diese Vorlage im Auslieferungszustand mit echten Daten: der Mähbarkeitsindex für Bad Münder, berechnet aus dem kostenfreien OpenWeather-Zugang und alle 15 Minuten über einen Cronjob aktualisiert. Zu sehen sind alle Bausteine – Empfehlung, Indexwert mit Farbskala, die ausgeführten Prüfungen mit ihren Begründungen, der Erklärkasten und die an die MFI-API gesendeten Messwerte.
Zum Ausprobieren lohnt der Umschalter oben rechts für das dunkle Design. Der Bodentemperatur-Check fehlt dort bewusst: OpenWeather liefert im kostenfreien Zugang keine Bodenwerte, weshalb die Prüfung automatisch ausgeblendet wird.
| Funktion | Was sie leistet |
|---|---|
| MFI-Darstellung | Empfehlung im Klartext, Indexwert mit Farbskala, alle fünf Prüfungen mit Begründungen der API, Angaben zur Messung |
| Frei platzierbare Bausteine | mfi_result(), mfi_explain() und mfi_input_table() setzen den MFI an beliebiger Stelle ein – auf der Startseite oder jeder Unterseite |
| Einrichtungsassistent | Vier Schritte im Browser, prüft jede Eingabe live, schreibt die Konfiguration, legt die Tabelle an und entfernt sich danach selbst |
| OpenWeather-Anbindung | Wetterdaten kommen aus dem kostenfreien OpenWeather-Zugang und werden automatisch auf die Felder der MFI-API abgebildet |
| Werte aus eigener Historie | Regensummen, Zeit seit dem letzten Regen und Minimaltemperaturen werden aus den gespeicherten Läufen abgeleitet – Werte, die OpenWeather nicht liefert |
| Zwei Betriebsarten | Klassischer Cronjob (CLI oder tokengeschützte URL) oder Aktualisierung beim Seitenaufruf |
| Schutz vor Überlastung | Sperre gegen Parallelläufe, Mindestabstand zwischen Läufen, hartes Tageslimit für API-Abrufe |
| Eigene Seiten | Datei in pages/ ablegen genügt – Navigation, Meta-Angaben und Sitemap ziehen automatisch nach |
| Update-sicher | Eigene Seiten, eigene Gestaltung und die Konfiguration liegen außerhalb der Versionsverwaltung und überstehen jedes Update |
| Barrierefrei | WCAG 2.2 AA in hellem und dunklem Design, nachgemessene Kontraste, Status nie nur farbcodiert, vollständig ohne Maus und ohne JavaScript bedienbar |
| DSGVO-freundlich | Keine Cookies, kein Tracking, keine externen Ressourcen – alles liegt auf dem eigenen Server |
| SEO-Grundgerüst | Meta-Angaben, Open Graph, JSON-LD inklusive Indexwert als Dataset, automatische sitemap.xml und robots.txt |
| Fehlerbehandlung | Besucher sehen nie Serverpfade oder Stacktraces; Einzelheiten landen in var/error.log |
| Diagnose | bin/check-setup.php prüft Umgebung, Datenbank, API-Erreichbarkeit und Rechte auf einen Schlag |
| Anforderung | Details |
|---|---|
| PHP | ab 8.2 mit pdo_mysql, curl, json, mbstring – empfohlen 8.3 oder neuer |
| Datenbank | MySQL 8.0+ oder MariaDB 10.4+ (Fensterfunktionen werden genutzt) |
| Webserver | Apache mit mod_rewrite (.htaccess liegt bei) |
| MFI-API-Key | kostenlos unter maehbarkeitsindex.de/api/registrieren |
| Wetter-API-Key | kostenlos bei OpenWeather |
Kein Composer, kein npm, kein Build-Schritt.
Hinweis zu den Schlüsseln: MFI-API-Keys werden nach der Registrierung von Hand freigeschaltet. Frisch erstellte OpenWeather-Keys brauchen erfahrungsgemäß einige Stunden, bis sie funktionieren.
public/ ist das öffentliche Verzeichnis und sollte als DocumentRoot eingestellt sein.
Alle übrigen Ordner liegen darüber und sind damit nicht über das Web erreichbar. Lässt sich
der DocumentRoot nicht umstellen, siehe Hosting ohne eigenen DocumentRoot.
git clone https://github.com/CSWebations/mfi-example-page.git
cd mfi-example-pageAnschließend das Verzeichnis auf den Server bringen oder direkt dort klonen. Aktualisieren später mit:
git pullEigene Inhalte bleiben dabei unangetastet – siehe Was Updates überstehen.
- Aktuelle Fassung als ZIP herunterladen und entpacken. Alternativ über Code → Download ZIP auf der Projektseite oder unter Releases eine bestimmte Version.
- Den Inhalt des entpackten Ordners per FTP auf den Server laden.
- Sicherstellen, dass das Verzeichnis
var/für den Webserver beschreibbar ist (z. B.0775).
Rufen Sie Ihre Domain auf. Solange keine Konfiguration existiert, leitet die Seite selbsttätig auf den Assistenten weiter.
| Schritt | Inhalt |
|---|---|
| 1 – System | PHP-Version, Erweiterungen und Schreibrechte werden geprüft |
| 2 – Datenbank | Zugangsdaten werden sofort ausprobiert, nicht nur auf Vollständigkeit geprüft |
| 3 – API-Zugänge | MFI-API und OpenWeather werden mit echten Abrufen getestet |
| 4 – Website | Name, Adresse, Betriebsart und Intervall |
Zum Abschluss schreibt der Assistent die Konfiguration, legt die Datenbanktabelle an, berechnet den ersten Indexwert, zeigt die passende Cron-Zeile mit Ihrem Serverpfad und löscht sich anschließend selbst.
Zugriffsschutz: Der erste Aufruf reserviert die Einrichtung für den aufrufenden Browser – andere sehen bis zum Abschluss nur einen Hinweis. Eine Frist gibt es nicht: Sie können jederzeit unterbrechen, Zugangsdaten heraussuchen und später weitermachen. Kommen Sie selbst nicht mehr an die begonnene Einrichtung heran, löschen Sie
var/setup-claim.json.
Eingestellt wird die Betriebsart im Assistenten oder später über runtime.mode.
Ein Cronjob aktualisiert im Hintergrund, die Website liest nur aus der Datenbank. Seitenaufrufe bleiben dadurch schnell und lösen keine API-Aufrufe aus.
*/15 * * * * /usr/bin/php /pfad/zum/projekt/bin/update.php --quietZum Pfad des PHP-Programms: Der obige ist nur der häufigste – je nach Hoster liegt es
woanders oder heißt versionsbezogen, etwa /usr/bin/php8.3. Der Assistent ermittelt den
Pfad und zeigt die fertige Zeile an; nachträglich nennt sie auch php bin/check-setup.php.
Meldet der Cronjob „no such file or directory", stimmt der Pfad nicht: In der
Kommandozeile findet ihn which php, andernfalls hilft die Dokumentation des Hosters.
Manche Cron-Formulare erwarten ohnehin nur den Pfad zur Datei und wählen PHP selbst aus.
Ohne Shell-Zugang – oder wenn der Pfad Schwierigkeiten macht – übernimmt ein externer Cron-Dienst den Aufruf dieser Adresse. Das funktioniert bei jedem Hoster, weil keinerlei Pfadangabe nötig ist:
https://ihre-domain.de/cron.php?token=IHR_TOKEN
Das Token steht in der Konfiguration unter runtime.cron_token und wird vom Assistenten
erzeugt. Ohne gesetztes Token verweigert cron.php jeden Aufruf.
Kein Cronjob nötig: Sind die Daten älter als das eingestellte Intervall, werden sie beim nächsten Besuch erneuert. Dafür wartet der erste Besucher auf die beiden API-Aufrufe. Eine Dateisperre verhindert, dass gleichzeitige Zugriffe mehrere Aktualisierungen auslösen.
php bin/check-setup.php # Einrichtung prüfen (mit --full inkl. Testabruf)
php bin/update.php --force # sofort aktualisieren, Mindestabstand ignorieren
php bin/cleanup.php # alte Datensätze entfernenDas Standard-Rate-Limit der MFI-API liegt bei 300 Sekunden pro Key. Intervalle darunter führen zu HTTP 429. Details in der API-Dokumentation.
Die Ausgabe besteht aus drei Bausteinen, die als PHP-Kurzformen auf jeder Seite in
pages/ zur Verfügung stehen:
<?= mfi_result() ?> <!-- Empfehlung, Indexwert, Prüfungen, Angaben zur Messung -->
<?= mfi_explain() ?> <!-- Erklärkasten "Was bedeutet das?" -->
<?= mfi_input_table() ?> <!-- Tabelle der an die API gesendeten Messwerte -->Reihenfolge frei wählbar, einzelne Bausteine können entfallen, eigene Abschnitte dürfen
dazwischenstehen. Ohne vorliegendes Ergebnis zeigt mfi_result() einen Hinweis, während
mfi_input_table() leer bleibt.
Für eigene Logik:
<?php if (mfi_has_result()): ?>
<p>Aktueller Wert: <?= mfi_data()->score() ?> von 100</p>
<?php endif; ?>mfi_data() liefert unter anderem score(), mainStatus(), scaleStep(), createdAt(),
dataQuality(), season(), checks() und inputFields().
Die Startseite ist eine gewöhnliche Inhaltsseite und enthält außer den Bausteinen nur Überschrift und Einleitung. Zum Bearbeiten kopieren:
cp pages-default/home.php pages/home.phpAb dann gilt Ihre Fassung. Sie können den MFI dort auch vollständig entfernen und stattdessen auf einer Unterseite ausgeben.
Eine neue Seite entsteht durch eine neue Datei in pages/. Der Dateiname wird zur Adresse:
aus pages/rasenpflege.php wird /rasenpflege. Der Kommentarkopf steuert den Rest:
<?php
/**
* Title: Rasenpflege im Sommer
* Description: Worauf es beim Mähen an heißen Tagen ankommt.
* Nav: Rasenpflege
* NavOrder: 30
* Sitemap: 0.6 monthly
*/
?>
<section class="section">
<div class="container">
<h1>Rasenpflege im Sommer</h1>
</div>
</section>| Angabe | Bedeutung |
|---|---|
Title |
Seitentitel für <title>, Open Graph und JSON-LD |
Description |
Meta-Description |
Nav |
Beschriftung in der Navigation; fehlt sie, erscheint die Seite dort nicht |
NavOrder |
Sortierung, kleiner heißt weiter vorn (Standard 100) |
Sitemap |
Priorität und Änderungshäufigkeit, z. B. 0.6 monthly; - schließt aus |
Noindex |
true setzt die Seite auf noindex |
Mitgelieferte Seiten bearbeiten: Die Vorlagen liegen in pages-default/. Kopieren Sie
die gewünschte Datei nach pages/ und ändern Sie dort – Ihre Fassung hat Vorrang und
bleibt bei Updates erhalten.
cp pages-default/beispielseite.php pages/meine-seite.phppages-default/beispielseite.php enthält bewusst nur Platzhalter und zeigt die
verfügbaren Bausteine: Überschriften, Fließtext, Listen, Tabelle und Schaltflächen.
Impressum und Datenschutzerklärung müssen Sie selbst anlegen. Beide sind für den Betrieb einer Website in aller Regel verpflichtend, hängen aber von Ihrer Rechtsform, Ihrem Hosting und den von Ihnen eingesetzten Diensten ab – deshalb kann das Projekt sie nicht mitliefern. Legen Sie die Seiten wie oben beschrieben in
pages/an (etwapages/impressum.phpundpages/datenschutz.php) und lassen Sie die Texte im Zweifel rechtlich prüfen.
Alles, was Ihnen gehört, ist von der Versionsverwaltung ausgenommen:
| Ihr Bereich | Mitgeliefertes Gegenstück |
|---|---|
pages/ |
pages-default/ |
partials/ |
src/templates/partials/ |
public/assets/css/user-style.css |
user-style.example.css |
config.php |
config.sample.php |
Eine Datei aus dem rechten in den linken Bereich zu kopieren genügt, um sie zu übernehmen. Ab dann gilt Ihre Fassung, und das Original darf sich bei Updates weiterentwickeln.
Beide lassen sich vollständig ersetzen. Kopieren Sie die gewünschte Vorlage in das
Verzeichnis partials/:
cp src/templates/partials/footer.php partials/footer.phpAb dann verwendet die Website ausschließlich Ihre Fassung – auch nach einer
Aktualisierung. Dasselbe gilt für header.php und badge.php.
Das ist auch der Ort für Verweise auf Seiten, die nicht in der Hauptnavigation erscheinen sollen – etwa Impressum und Datenschutzerklärung:
<li><a class="site-footer__link" href="/impressum">Impressum</a></li>
<li><a class="site-footer__link" href="/datenschutz">Datenschutz</a></li>Welche Hilfsmittel Ihnen darin zur Verfügung stehen, steht in partials/LIESMICH.md.
Ihre Fassung erhält keine künftigen Verbesserungen am mitgelieferten Kopf- oder Fußbereich mehr. Nach einer Aktualisierung lohnt ein Blick in
src/templates/partials/, ob dort etwas hinzugekommen ist.
Farben und Abstände. Über eine eigene Stylesheet-Datei, die nach dem Theme geladen wird und damit jeden Konflikt gewinnt:
cp public/assets/css/user-style.example.css public/assets/css/user-style.cssDie Vorlage listet alle Farb- und Abstandsvariablen auskommentiert auf. Die Voreinstellungen erfüllen WCAG 2.2 AA in beiden Designs – wer Farben ersetzt, sollte die Kontraste nachmessen (mindestens 4,5:1 für Text, 3:1 für grafische Elemente).
Logo. Ohne Angabe erscheint der Name der Website als Text. Ein Logo wird über
site.logo eingebunden (Pfad relativ zum Webroot), bei Bedarf mit eigener Fassung fürs
dunkle Design über site.logo_dark.
Prüfungen ausblenden. Über display.checks je Prüfung:
| Wert | Wirkung |
|---|---|
auto |
nur zeigen, wenn die Prüfung ausgeführt wurde (Standard) |
always |
immer zeigen, auch als „nicht bewertet" |
never |
nie zeigen |
Mit auto verschwindet der Bodentemperatur-Check von selbst, weil der kostenfreie
OpenWeather-Zugang keine Bodenwerte liefert.
Texte. Sämtliche sichtbaren Texte des Grundgerüsts stehen in src/lang/de.php.
Der kostenfreie OpenWeather-Zugang liefert Temperatur, Luftfeuchtigkeit, Wind, Böen und den Niederschlag der letzten Stunde. Bodentemperatur und Bodenfeuchte fehlen, deshalb überspringt die MFI-API den Bodencheck und weist die Datenqualität als „teilweise" aus.
Fehlende Langzeitwerte ergänzt das Projekt selbst aus den gespeicherten Läufen:
| Feld | Ableitung |
|---|---|
rain_12h, rain_24h, rain_14d |
Summe stündlicher Stichproben |
minutes_since_rain |
Zeit seit der letzten Messung mit Niederschlag |
min_temp_3h, min_temp_3d, min_temp_14d |
Tiefstwert im jeweiligen Zeitfenster |
Ein abgeleitetes Feld wird nur gesendet, wenn das Zeitfenster zu mindestens 80 Prozent belegt ist. Direkt nach der Installation fehlen die längeren Fenster daher noch – sie kommen nach und nach dazu. In der Tabelle der gesendeten Messwerte ist jederzeit erkennbar, welcher Wert von der Quelle stammt und welcher abgeleitet wurde.
Lässt sich der DocumentRoot nicht auf public/ legen, verschieben Sie den Inhalt von
public/ ins Webroot-Verzeichnis, während die übrigen Ordner eine Ebene darüber bleiben.
In der verschobenen index.php und cron.php ist dann der Pfad zu src/bootstrap.php
anzupassen. Die .htaccess sperrt vorsorglich auch dann den Zugriff auf Konfigurations-,
SQL- und Protokolldateien, wenn doch einmal alles im Webroot liegt.
| Meldung | Ursache und Abhilfe |
|---|---|
| „Website noch nicht eingerichtet" | Konfiguration fehlt oder ist unvollständig – Assistent unter /setup.php aufrufen |
| „Die Einrichtung läuft bereits" | Der Assistent gehört einem anderen Browser – var/setup-claim.json löschen |
| „Noch kein Mähbarkeitsindex verfügbar" | Es gab noch keinen erfolgreichen Lauf – php bin/update.php ausführen |
| HTTP 401 | MFI-API-Key falsch oder nicht übernommen |
| HTTP 403 | Key noch nicht freigeschaltet oder deaktiviert; Freischaltung erfolgt manuell |
| HTTP 422 | Pflichtfelder fehlen – die Wetterquelle liefert keine Temperatur oder keinen Niederschlag |
| HTTP 429 | Rate-Limit erreicht – Intervall erhöhen |
| HTTP 503 | Wartungsmodus der API – später erneut versuchen |
| OpenWeather 401 | Neue Keys werden erst nach einigen Stunden aktiv |
Fehler erreichen den Browser nie im Klartext. Erste Anlaufstelle ist var/error.log;
dort stehen Meldung, Datei, Zeile und Aufrufweg. Fehlgeschlagene Läufe landen zusätzlich in
der Tabelle mfi_results mit ihrer Fehlermeldung. Für die Fehlersuche lässt sich
runtime.debug vorübergehend auf true setzen – im Regelbetrieb gehört der Wert auf
false, sonst werden Serverpfade für jeden Besucher sichtbar.
Bei Nutzung der MFI-API ist die Quelle anzugeben. Das mitgelieferte Badge im Fußbereich verlinkt auf maehbarkeitsindex.de und erfüllt diese Anforderung. Weitere Varianten stehen im Styleguide.
- Live-Demo dieser Vorlage – der Auslieferungszustand mit echten Daten
- Was ist der Mähbarkeitsindex? – Hintergrund und Berechnungsmodell
- API-Übersicht und Schnellstart
- Endpunkt
/v1/calculate– alle Felder und Wertebereiche - Regeln und HTTP-Codes
- API-Key registrieren
- MFI-Demo des Anbieters – dieselbe Datenquelle, andere Darstellung
- OpenWeather-Konto anlegen
MIT für den Code dieses Projekts.
Bootstrap 5.3 und Bootstrap Icons stehen unter MIT-Lizenz. Die MFI-Logos und -Badges sind geschützte Kennzeichen von maehbarkeitsindex.de und dürfen ausschließlich zur Quellenangabe verwendet werden.