srhinow / simple-map-bundle
simple maps width pins for Contao CMS based on OSM and Mapbox
Package info
gitlab.com/srhinow/simple-map-bundle
Type:contao-bundle
pkg:composer/srhinow/simple-map-bundle
Requires
- php: >=8.3
- ext-json: *
- contao/core-bundle: ^5.3
- league/csv: ^9.16
- menatwork/contao-multicolumnwizard-bundle: ^3.6.8
Requires (Dev)
- phpunit/phpunit: ^11.5
This package is auto-updated.
Last update: 2026-05-13 19:20:07 UTC
README
Interaktive Karten mit Markern für Contao CMS — zentral verwaltet im Backend, eingebunden per Inhaltselement oder Frontend-Modul. Basiert auf OpenStreetMap-Kacheln (oder optional Mapbox), der Leaflet-JavaScript-Bibliothek und der Nominatim-API für automatische Geocodierung.
Anforderungen
| Abhängigkeit | Version |
|---|---|
| PHP | ≥ 8.3 |
| Contao Core Bundle | ^5.3 |
| league/csv | ^9.16 |
| menatwork/contao-multicolumnwizard-bundle | ^3.6.8 |
| ext-json | * |
Installation
composer require srhinow/simple-map-bundle
Nach der Installation die Datenbank-Migration ausführen:
php bin/console contao:migrate
Leaflet CSS/JS wird automatisch über $GLOBALS['TL_HEAD'] aus dem Bundle-Public-Verzeichnis (bundles/srhinowsimplemap/leaflet/) eingebunden — keine manuelle Asset-Konfiguration erforderlich.
Backend
Das Bundle fügt im Contao-Backend die Gruppe „OSM Maps" hinzu mit drei Verwaltungsbereichen:
1. Karten (tl_simple_map)
Jede Karte definiert Mittelpunkt, Zoom-Stufe, Kartenlayer (OSM oder Mapbox) und optionalen benutzerdefinierten Leaflet-Code. Marker werden als Kindeinträge zur Karte verwaltet.
Felder:
| Feld | Beschreibung |
|---|---|
| Titel | Eindeutige Bezeichnung der Karte (Pflichtfeld) |
| Alias | URL-freundlicher Bezeichner (automatisch generiert) |
| Straße / Nr. | Adresse des Kartenzentrums |
| PLZ / Ort | Adresse des Kartenzentrums |
| Sprache | Locale für die Adressauflösung (Standard: de) |
| Koordinaten auflösen | Checkbox: löst mapLat/mapLon per Nominatim aus der Adresse auf |
| Pin erzeugen | Checkbox: legt automatisch einen Marker aus der Kartenadresse an |
| Breitengrad / Längengrad | Kartenmittelpunkt (DECIMAL(10,8) / DECIMAL(11,8)) |
| Zoom | Initiale Zoom-Stufe (Ganzzahl, typisch 5–18) |
| Leaflet-Script | Eigener JavaScript-Code, der nach der Karteninitialisierung ausgeführt wird (ACE-Editor, JS-Syntax). Erhält mymap und L als Parameter. Standard: mymap.scrollWheelZoom.disable(); |
| Mapbox aktivieren | Checkbox: wechselt den Tile-Layer von OSM auf Mapbox (klappt Unterpalette auf) |
| Mapbox API-Key | Pflicht wenn Mapbox aktiv, eindeutig pro Installation |
| Mapbox-Style | Style-Identifier, z. B. mapbox/streets-v12 |
2. Kategorien (tl_simple_map_category)
Optionale Kategorien für die Gruppierung von Markern in der Kategorielisten-Ansicht.
| Feld | Beschreibung |
|---|---|
| Titel | Eindeutiger Kategoriename (Pflichtfeld) |
| Alias | Automatisch generiert, alphanumerisch |
| Sortierung | Numerischer Sortierwert für die Reihenfolge in der Kategorieliste |
3. Marker / Pins (tl_simple_map_pin)
Marker sind Kindeinträge einer Karte und werden in der Karten-Listenansicht über die Operation „Pins" aufgerufen. Die Listenansicht zeigt Titel, Straße, Nr., PLZ, Ort und Kategorie als Spalten.
Felder:
| Feld | Beschreibung |
|---|---|
| Titel | Bezeichnung des Markers (max. 255 Zeichen) |
| Kategorie | Optionale Zuweisung zu einer tl_simple_map_category |
| Straße / Nr. | Adresse des Markers |
| PLZ / Ort | Adresse des Markers |
| Sprache | Locale für die Adressauflösung |
| Koordinaten auflösen | Checkbox: löst mapLat/mapLon per Nominatim aus der Adresse auf |
| Breitengrad / Längengrad | Marker-Position (DECIMAL) |
| Popup-Text | HTML-Inhalt des Leaflet-Popups (TinyMCE-Editor, Insert-Tags werden geparst) |
| Popup geöffnet | Checkbox: Popup wird beim Laden der Karte sofort geöffnet |
| Online sichtbar | Veröffentlichungs-Flag |
CSV-Import
Marker können per CSV-Datei massenimportiert werden. Die Operation „CSV importieren" öffnet ein Import-Formular mit:
- Auswahl einer CSV-Datei aus
files/csv_imports/ - Feldmapping per Multi-Column-Wizard: linke Spalte = CSV-Spaltenname, mittlere Spalte = Zielfeld in
tl_simple_map_pin, rechte Spalte = fester Standardwert - Offset / Limit für seitenweisen Import großer Dateien
- Optionaler Geocodierung aller importierten Marker nach dem Import
Verfügbare Import-Felder:
Alle Spalten der Tabelle tl_simple_map_pin außer id, pid, tstamp — die Optionsliste wird dynamisch aus dem Datenbankschema gelesen.
Frontend
Das Bundle stellt zwei Frontend-Typen bereit, die jeweils als Inhaltselement und als Frontend-Modul verfügbar sind:
simple_map_view — Kartenansicht
Rendert die interaktive Leaflet-Karte mit allen veröffentlichten Markern der ausgewählten Karte.
Backend-Einstellung: simpleMap — Dropdown zur Auswahl einer Karte aus tl_simple_map.
Funktionsweise:
- Lädt Kartenkonfiguration aus
tl_simple_map - Lädt alle veröffentlichten Pins (
published=1) der Karte - Parst Insert-Tags und ersetzt
[nbsp]inpopupText - Normalisiert Koordinaten (Komma → Punkt, Fallback auf 0)
- Bindet Leaflet CSS/JS über
$GLOBALS['TL_HEAD']ein - Schreibt Kartenkonfiguration als JSON in ein
data-simple-map-Attribut - Initialisiert die Karte per Inline-Script nach
DOMContentLoaded
Templates:
- Inhaltselement:
contao/templates/content_element/simple_map_view.html.twig - Frontend-Modul:
contao/templates/frontend_module/simple_map_view.html.twig
Template-Variablen:
| Variable | Typ | Beschreibung |
|---|---|---|
error | bool | true wenn Karte oder Pins nicht gefunden |
msg | string | Fehlermeldung (aus TL_LANG['MSC']) |
mapId | string | Eindeutige HTML-ID des Karten-Containers (map{id}) |
map | array | Kompletter tl_simple_map-Datensatz (alle Felder) |
marker | array | Array von Pin-Datensätzen (alle Felder + normalisierte Koordinaten) |
data-simple-map JSON-Struktur (automatisch vom Template erstellt):
{
"lat": 52.5200,
"lon": 13.4050,
"zoom": 12,
"doMapbox": false,
"mapboxStyle": "",
"mapboxApiKey": "",
"customScript": "mymap.scrollWheelZoom.disable();",
"marker": [
{
"lat": 52.5200,
"lon": 13.4050,
"popupText": "<b>Mein Ort</b>",
"popupOpen": false
}
]
}
simple_map_category_list — Kategorieliste
Zeigt die Popup-Texte aller Marker nach Kategorie gruppiert als Accordion-Liste — ohne Karte, als reine Textübersicht.
Backend-Einstellung: wie simple_map_view — simpleMap-Dropdown.
Templates:
- Inhaltselement:
contao/templates/content_element/simple_map_category_list.html.twig - Frontend-Modul:
contao/templates/frontend_module/simple_map_category_list.html.twig
Template-Variablen:
| Variable | Typ | Beschreibung |
|---|---|---|
error | bool | true wenn Karte oder Pins nicht gefunden |
msg | string | Fehlermeldung |
map | array | tl_simple_map-Datensatz |
categories | array | Sortiertes Array der Kategorien (nach sorting-Feld) |
marker | array | Assoziatives Array: marker[categoryId][] = Pin-Datensätze |
Jeder categories-Eintrag enthält alle Felder aus tl_simple_map_category (id, title, alias, sorting).
Templates anpassen
Alle Templates liegen unter contao/templates/. Für projektspezifische Anpassungen die gewünschte Datei in den Projekt-Templates-Ordner kopieren:
templates/
└── bz-niedersachsen/
├── content_element/
│ ├── simple_map_view.html.twig
│ └── simple_map_category_list.html.twig
└── frontend_module/
├── simple_map_view.html.twig
└── simple_map_category_list.html.twig
Leaflet-Custom-Script
Das Feld „Leaflet-Script" erlaubt beliebigen JavaScript-Code, der nach der Karteninitialisierung ausgeführt wird. Der Code wird in eine Funktion eingekapselt, die zwei Parameter erhält:
mymap— die Leaflet-Karten-InstanzL— das globale Leaflet-Objekt
Beispiele:
// Scroll-Zoom deaktivieren (Standard)
mymap.scrollWheelZoom.disable();
// Karte auf Marker-Bounds zoomen
mymap.fitBounds(mymap.getBounds().pad(0.2));
// Eigenen Tile-Layer hinzufügen
L.tileLayer('https://...).addTo(mymap);
Fehler werden in der Browser-Konsole als Leaflet Custom Script Error: geloggt.
Geocodierung (Nominatim)
Die Koordinatenauflösung erfolgt über die OpenStreetMap Nominatim API (nominatim.openstreetmap.org/search). Sie wird ausgelöst durch:
- Aktivieren der Checkbox „Koordinaten auflösen" beim Speichern einer Karte oder eines Markers
- Automatisch bei neuen Markern ohne vorhandene Koordinaten
- Optionaler Durchlauf nach dem CSV-Import
Der gesendete Such-String setzt sich zusammen aus: Straße Nr, PLZ Ort (je nach verfügbaren Feldern). Das Ergebnis setzt mapLat und mapLon im Datensatz.
Datenbankstruktur
tl_simple_map
| Spalte | Typ | Beschreibung |
|---|---|---|
id | int(10) unsigned | Primärschlüssel |
tstamp | int(10) unsigned | Zeitstempel letzte Änderung |
title | varchar(255) | Eindeutiger Kartentitel |
alias | varchar(64) | URL-Alias |
street | varchar(128) | Straße des Zentrums |
nr | varchar(28) | Hausnummer |
postal | varchar(32) | PLZ |
city | varchar(255) | Ort |
language | varchar(5) | Locale (Standard: de) |
setNewGeo | char(1) | Geocodierungs-Trigger |
setNewPin | char(1) | Auto-Pin-Trigger |
mapLat | decimal(10,8) NULL | Breitengrad des Zentrums |
mapLon | decimal(11,8) NULL | Längengrad des Zentrums |
mapZoom | int(10) unsigned | Zoom-Stufe (Standard: 5) |
leafletCustomScript | text | Benutzerdefinierter Leaflet-JS-Code |
do_mapbox | char(1) | Mapbox-Layer aktiviert |
mapboxApiKey | varchar(255) | Mapbox API-Key |
mapboxStyle | varchar(255) | Mapbox Style-ID (Standard: mapbox/streets-v12) |
tl_simple_map_pin
| Spalte | Typ | Beschreibung |
|---|---|---|
id | int(10) unsigned | Primärschlüssel |
pid | int(10) unsigned | Eltern-Karte (tl_simple_map.id) |
tstamp | int(10) unsigned | Zeitstempel |
title | varchar(255) | Marker-Bezeichnung |
category | varchar(64) | Kategorie-ID (FK → tl_simple_map_category) |
street | varchar(128) | Straße |
nr | varchar(28) | Hausnummer |
postal | varchar(32) | PLZ |
city | varchar(255) | Ort |
language | varchar(5) | Locale |
setNewGeo | char(1) | Geocodierungs-Trigger |
mapLat | decimal(10,8) NULL | Breitengrad |
mapLon | decimal(11,8) NULL | Längengrad |
popupText | blob NULL | Popup-Inhalt (HTML, Insert-Tags möglich) |
popupOpen | char(1) | Popup beim Laden geöffnet |
published | char(1) | Veröffentlicht |
importCsvFile | varchar(255) | Zuletzt verwendete CSV-Datei (Import) |
importMatchMapPinFields | blob NULL | Feldmapping-Konfiguration (Multi-Column-Wizard) |
importOffset | int(10) unsigned | Import-Offset (Standard: 0) |
importLimit | int(10) unsigned | Import-Limit (Standard: 50) |
tl_simple_map_category
| Spalte | Typ | Beschreibung |
|---|---|---|
id | int(10) unsigned | Primärschlüssel |
tstamp | int(10) unsigned | Zeitstempel |
title | varchar(255) | Eindeutiger Kategorietitel |
alias | varchar(64) | URL-Alias |
sorting | varchar(255) | Sortierungswert |
Tests ausführen
Aus dem Haupt-Contao-Verzeichnis:
vendor/bin/phpunit -c vendor/srhinow/simple-map-bundle/phpunit.xml.dist
Aus dem Bundle-Root (wenn vendor/ vorhanden):
vendor/bin/phpunit
Lizenz
LGPL-3.0-or-later
Autor
Sven Rhinow — sr-tag.de
Support: kservice@sr-tag.de
Quellcode: gitlab.com/srhinow/simple-map-bundle