Mai 2026 – Maintenance-Status: Ab Version 4.6 werden keine neuen Features mehr entwickelt. MBlock ist stabil und weiterhin voll funktionsfähig, befindet sich aber im reinen Wartungsmodus. Fehlerbehebungen und wichtige Stabilitätskorrekturen werden weiterhin umgesetzt.
Mit MBlock ist es möglich, innerhalb eines Moduls beliebig viele Datenblöcke zu erzeugen. Diese können per Button oder Drag & Drop sortiert werden. Die erweiterte Version bietet Copy & Paste und einen Online/Offline-Toggle für einzelne Blöcke.
English: MBlock lets you create an unlimited number of data blocks within a single module, sortable by click or drag & drop. The enhanced version provides copy & paste and an offline/online toggle for individual blocks.
MForm >= 9: Für neue Module ist MForm 9 mit dem integrierten Flex-Repeater die modernere Wahl. MBlock bleibt für bestehende Projekte vollständig nutzbar.
Copy & Paste funktioniert mit diesen Editoren nicht und sollte in den betreffenden Modulen deaktiviert werden:
echo MBlock::show(1, $form, [
'copy_paste' => false,
]);- Beliebig viele Datenblöcke pro Modul
- Drag & Drop Sortierung
- Min/Max Anzahl von Blöcken definierbar
- MForm Integration – alle MForm-9-Felder werden unterstützt
- Template-System mit Custom-Template-Unterstützung
- Online/Offline Toggle – Blöcke aktivieren/deaktivieren ohne löschen
- Copy & Paste – Duplizierung von Blöcken
- Frontend API –
filterByField(),sortByField(),groupByField() - TinyMCE / CKEditor 5 – volle Editor-Unterstützung
- Mehrsprachigkeit (DE/EN)
# Via REDAXO Installer:
# System > Installer > "mblock" suchen > installierenSeit Version 4.0 steht der Namespace FriendsOfRedaxo\MBlock zur Verfügung. Die Legacy-Syntax ohne Namespace ist weiterhin vollständig kompatibel.
<?php
use FriendsOfRedaxo\MBlock\MBlock;
$items = MBlock::getOnlineDataArray("REX_VALUE[1]");
echo MBlock::show(1, $mform->show());<?php
use FriendsOfRedaxo\MBlock\MBlock;
// Alle Blöcke (inkl. offline)
$allItems = MBlock::getDataArray("REX_VALUE[1]");
// Nur Online-Blöcke – empfohlen für das Frontend
$onlineItems = MBlock::getOnlineDataArray("REX_VALUE[1]");
// oder:
$onlineItems = MBlock::getDataArray("REX_VALUE[1]", 'online');
// Nur Offline-Blöcke
$offlineItems = MBlock::getOfflineDataArray("REX_VALUE[1]");<?php
use FriendsOfRedaxo\MBlock\MBlock;
$items = MBlock::getOnlineDataArray("REX_VALUE[1]");
// Filtern
$newsItems = MBlock::filterByField($items, 'category', 'news');
// Sortieren
$sorted = MBlock::sortByField($items, 'date', 'DESC', 'date');
// Gruppieren
$grouped = MBlock::groupByField($items, 'category');
foreach ($grouped as $category => $categoryItems) {
echo '<h2>' . rex_escape($category) . '</h2>';
foreach ($categoryItems as $item) {
echo '<p>' . rex_escape($item['title']) . '</p>';
}
}
// Anzahl begrenzen (für Pagination)
$topItems = MBlock::limitItems($items, 5);
$nextItems = MBlock::limitItems($items, 5, 5);foreach (MBlock::getDataArray("REX_VALUE[1]") as $item) {
if (MBlock::isOnline($item)) {
echo rex_escape($item['title']);
}
}Hinweis:
MBlock::getOnlineItems()undgetOfflineItems()(alte Signatur mit Array-Parameter) sind deprecated. BittegetOnlineDataArray()/getOfflineDataArray()verwenden.
MBlock arbeitet am besten zusammen mit MForm. MForm 9 ist vollständig kompatibel – alle Felder funktionieren in MBlock.
| Methode | Kategorie | Hinweis |
|---|---|---|
addTextField() |
Text | ✅ uneingeschränkt |
addTextAreaField() |
Text | ✅ uneingeschränkt |
addHiddenField() |
Text | ✅ uneingeschränkt |
addSelectField() |
Auswahl | ✅ uneingeschränkt |
addMultiSelectField() |
Auswahl | ✅ uneingeschränkt |
addCheckboxField() |
Auswahl | ✅ uneingeschränkt |
addToggleCheckboxField() |
Auswahl | ✅ uneingeschränkt |
addRadioField() |
Auswahl | ✅ uneingeschränkt |
addRadioImgField() |
Auswahl | ✅ uneingeschränkt |
addRadioIconField() |
Auswahl | ✅ uneingeschränkt |
addRadioColorField() |
Auswahl | ✅ uneingeschränkt |
addMediaField(n) |
Media/Link | ✅ Ausgabe: $item['REX_MEDIA_n'] · mit useCustomLinkForClassicWidgets(true) kein Klonen-Problem |
addMedialistField(n) |
Media/Link | ✅ Ausgabe: $item['REX_MEDIALIST_n'] |
addLinkField(n) |
Media/Link | ✅ Ausgabe: $item['REX_LINK_n'] · mit useCustomLinkForClassicWidgets(true) kein Klonen-Problem |
addLinklistField(n) |
Media/Link | ✅ Ausgabe: $item['REX_LINKLIST_n'] |
addMFormMediaField("$id.0.key") |
Media/Link | ✅ MForm-native, kein Reindex-Problem · Ausgabe: $item['key'] |
addCustomLinkField("$id.0.key") |
Media/Link | ✅ Ausgabe: $item['key'] · Normalisierung via MFormOutputHelper::createLinkData() empfohlen |
addCustomLinkMultipleField("$id.0.key") |
Media/Link | ✅ Neu in MForm 9 · gibt JSON-Array mit mehreren Links zurück |
addConditionalFieldsetArea() |
Layout | ✅ Neu in MForm 9 · regelbasierte Feldanzeige funktioniert in MBlock |
addFieldsetArea() |
Layout | ✅ uneingeschränkt |
Hinweis zu
addMediaField/addLinkFieldmit numerischer ID:
Beim Klonen von Blöcken in MBlock kann es ohneuseCustomLinkForClassicWidgets(true)zu Reindex-Problemen kommen, weil REDAXO-Widgets intern per Widget-ID referenziert werden. Mit dem Flag wird das custom_link-Widget verwendet – das Speicherformat (REX_MEDIA_n/REX_LINK_n) bleibt dabei identisch.
Moduleingabe:
<?php
use FriendsOfRedaxo\MForm;
use FriendsOfRedaxo\MBlock\MBlock;
$id = 1;
// useCustomLinkForClassicWidgets(true) sorgt dafür, dass addMediaField / addLinkField
// über das custom_link-Widget gerendert werden → kein Reindex-Problem beim Klonen.
// Das Speicherformat (REX_MEDIA_1 / REX_LINK_n) bleibt identisch.
MForm::useCustomLinkForClassicWidgets(true);
$mform = MForm::factory()
->addFieldsetArea('Team-Mitglied', MForm::factory()
->addTextField("$id.0.name", ['label' => 'Name'])
->addMediaField(1, ['label' => 'Avatar']) // → $item['REX_MEDIA_1']
->addCustomLinkField("$id.0.link", ['label' => 'Profil-Link', 'intern' => 1, 'extern' => 1]) // → $item['link']
->addHiddenField("$id.0.mblock_offline", '0') // Online/Offline-Toggle
);
MForm::useCustomLinkForClassicWidgets(false); // nur nötig wenn im selben Request weitere MForm-Instanzen ohne Flag folgen
echo MBlock::show($id, $mform->show(), [
'min' => 1,
'max' => 10,
'copy_paste' => true,
'online_offline' => true,
]);Modulausgabe:
<?php
use FriendsOfRedaxo\MBlock\MBlock;
use FriendsOfRedaxo\MForm\Utils\MFormOutputHelper;
$items = MBlock::getOnlineDataArray("REX_VALUE[1]");
foreach ($items as $item) {
$name = rex_escape($item['name'] ?? '');
$mediaName = $item['REX_MEDIA_1'] ?? '';
// Unified Link-Normalisierung (funktioniert mit String und Array-Format)
$link = MFormOutputHelper::createLinkData($item['link'] ?? '');
echo '<div class="team-member">';
if ($mediaName && ($media = rex_media::get($mediaName))) {
echo '<img src="' . rex_media_manager::getUrl('rex_media_medium', $media->getFileName()) . '"'
. ' alt="' . rex_escape($media->getTitle()) . '" class="img-responsive">';
}
if ($name) {
echo '<h3>' . $name . '</h3>';
}
if ('' !== $link['customlink_url']) {
echo '<a href="' . rex_escape($link['customlink_url']) . '"'
. $link['customlink_target'] . '>'
. rex_escape($link['customlink_text']) . '</a>';
}
echo '</div>';
}Für Projekte ohne MForm-Addon kann das Formular als HTML-String übergeben werden:
Moduleingabe:
<?php
use FriendsOfRedaxo\MBlock\MBlock;
$id = 1;
$form = <<<EOT
<fieldset>
<legend>Team-Mitglied</legend>
<div class="form-group">
<label>Name</label>
<input type="text" name="REX_INPUT_VALUE[$id][0][name]" value="" class="form-control">
</div>
<div class="form-group">
<label>Avatar</label>
REX_MEDIA[id="1" widget="1"]
</div>
</fieldset>
EOT;
echo MBlock::show($id, $form, [
'online_offline' => true,
'copy_paste' => true,
]);Modulausgabe:
<?php
use FriendsOfRedaxo\MBlock\MBlock;
$items = MBlock::getOnlineDataArray("REX_VALUE[1]");
foreach ($items as $item) {
$name = rex_escape($item['name'] ?? '');
$mediaId = $item['REX_MEDIA_1'] ?? '';
echo '<div class="team-member">';
echo '<h3>' . $name . '</h3>';
if ($mediaId && ($media = rex_media::get($mediaId))) {
echo '<img src="' . rex_media_manager::getUrl('rex_media_small', $media->getFileName()) . '"'
. ' alt="' . rex_escape($media->getTitle()) . '">';
}
echo '</div>';
}Je nach Methode und ID-Typ landen die Werte unter unterschiedlichen Schlüsseln im $item-Array.
addMediaField, addLinkField, addMedialistField, addLinklistField benötigen eine numerische ID. MBlock leitet daraus intern den REDAXO-Variablennamen ab:
| Methode | ID | Ausgabe-Schlüssel |
|---|---|---|
addMediaField(1) |
1 |
$item['REX_MEDIA_1'] |
addLinkField(2) |
2 |
$item['REX_LINK_2'] |
addMedialistField(3) |
3 |
$item['REX_MEDIALIST_3'] |
addLinklistField(4) |
4 |
$item['REX_LINKLIST_4'] |
Tipp: Mit
MForm::useCustomLinkForClassicWidgets(true)werden diese Felder intern über dascustom_link-Widget gerendert (moderner Widget-Stil, kein Reindex-Problem beim Klonen). Das Speicherformat bleibt identisch. In einem Modul-Input reicht der einmalige Aufruf –MForm::useCustomLinkForClassicWidgets(false)ist nur nötig, wenn im selben Request weitere MForm-Instanzen ohne das Flag folgen.
addCustomLinkField, addMFormMediaField sollten mit einem String-Pfad als ID verwendet werden. Das letzte Pfad-Segment wird zum JSON-Schlüssel:
| Methode | ID | Ausgabe-Schlüssel |
|---|---|---|
addCustomLinkField("$id.0.link") |
"$id.0.link" |
$item['link'] |
addMFormMediaField("$id.0.bild") |
"$id.0.bild" |
$item['bild'] |
Eine numerische ID wie
addCustomLinkField(6)erzeugt den wenig lesbaren Schlüssel$item['6']. String-Pfade sind immer vorzuziehen.
Custom-Link-Felder können je nach MForm-Version als String (redaxo://10) oder als Array mit id/name ankommen. MFormOutputHelper::createLinkData() normalisiert beide Formate:
use FriendsOfRedaxo\MForm\Utils\MFormOutputHelper;
$link = MFormOutputHelper::createLinkData($item['link'] ?? '');
// $link['customlink_url'] – fertige href-URL
// $link['customlink_text'] – Linktext (Artikelname, Media-Titel, URL-Fallback)
// $link['customlink_target'] – target-Attribut (z. B. ' target="_blank" ...')
// $link['customlink_class'] – CSS-Klasse (intern / external / media / mail / tel)echo MBlock::show($id, $form, [
'min' => 1, // Mindestanzahl Items (werden initial angezeigt)
'max' => 10, // Maximale Anzahl Items (0 = unbegrenzt)
'template' => 'modern', // Template-Name
'copy_paste' => true, // Copy & Paste aktivieren
'online_offline' => true, // Online/Offline-Toggle aktivieren
]);
online_offline: Erfordert einaddHiddenField("$id.0.mblock_offline", '0')im Formular.
Die Template-Auswahl erfolgt unter Addons > MBlock > Einstellungen. Das CSS wird automatisch in den assets/-Ordner kopiert.
Die mitgelieferten Templates unterstützen Dark Mode über:
body.rex-theme-dark(REDAXO Theme)@media (prefers-color-scheme: dark)(Browser)[data-bs-theme="dark"](Bootstrap 5)
Eigene Templates in redaxo/data/addons/mblock/templates/:
my_theme/
├── template.ini # Konfiguration
├── mblock_wrapper.ini # HTML-Wrapper für alle Items
├── mblock_element.ini # HTML-Template für einzelne Items
└── my_theme.css # CSS (gleicher Name wie der Ordner!)
MBlock verwendet drei modulare JavaScript-Dateien:
mblock-core.js– Utilities, Validierung, Übersetzungenmblock-management.js– DOM-Manipulation, Sortable-Handlingmblock-features.js– Copy/Paste, Online/Offline Toggle, REDAXO Widgets
cd redaxo/src/addons/mblock/build
./build.shErstellt automatisch:
mblock.js(Development)mblock.min.js(Production, minifiziert mit Terser)- Source Map für Debugging
Asset-Loading-Modi (konfigurierbar in boot.php):
| Modus | Verhalten |
|---|---|
auto (Standard) |
Development → mblock.js, Production → mblock.min.js |
modular |
3 separate Dateien (maximales Debugging) |
combined |
Immer mblock.js |
prod |
Immer mblock.min.js |
- Bearbeite die modularen Dateien in
assets/ cd build && ./build.shausführen- Im REDAXO-Debug-Modus wird automatisch die Development-Version geladen
Friends Of REDAXO
Project Leads