🚀 Vollständig optimiert für PHP 8.4+ mit der neuen DOM API!
doForm! neo nutzt jetzt die modernste PHP DOM API für maximale Performance und sauberen Code. Diese Version ist speziell für PHP 8.4+ optimiert und bietet eine deutlich verbesserte Entwicklererfahrung.
- Neue
\Dom\HTMLDocument
API statt veralteterDOMDocument
- CSS-Selektoren (
querySelector
,querySelectorAll
) statt XPath - Performance-Optimiert ohne Fallback-Overhead
- Modernste Type-Hints mit
\Dom\Element
- Match-Expressions für saubere Fehlerbehandlung
- Schlanker Code ohne Legacy-Unterstützung
- PHP >= 8.4
- DOM Extension (neue API)
- REDAXO >= 5.15
- UTF-8 Encoding Support
- Intelligente Label-Erkennung mit modernster DOM-Traversierung
- Radio-Button-Gruppierung via
fieldset/legend
oderdata-grouplabel
- Checkbox-Arrays und komplexe Formularstrukturen
- Sichere File-Uploads mit detaillierter Fehlerbehandlung
- Spam-Schutz mit Honeypot und Token-Validierung
- Reply-To-Unterstützung für E-Mail-Responses
- UTF-8-Optimiert mit automatischer Encoding-Erkennung
# Via Composer (empfohlen)
composer require klxm/doform-neo
# Oder manuell in REDAXO Backend installieren
<?php
use klxm\doform\FormProcessor;
$formHtml = '
<form method="post" enctype="multipart/form-data">
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
<label for="email">E-Mail</label>
<input type="email" id="email" name="email" required>
<label for="message">Nachricht</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Senden</button>
</form>';
$processor = new FormProcessor($formHtml, 'contact_form');
$processor->setEmailFrom('[email protected]');
$processor->setEmailTo('[email protected]');
$processor->setEmailSubject('Neue Kontaktanfrage');
$processor->setReplyToField('email');
$result = $processor->processForm();
if ($result === true) {
echo '<div class="success">Nachricht erfolgreich gesendet!</div>';
} elseif ($result === false) {
$processor->displayErrors();
$processor->displayForm();
} else {
$processor->displayForm();
}
?>
<!-- Moderne Label-Strukturen werden perfekt erkannt -->
<label>
Ihr Name:
<input type="text" name="name" required>
</label>
<label>
E-Mail-Adresse:
<input type="email" name="email" required>
</label>
<fieldset>
<legend>Anrede</legend>
<label><input type="radio" name="anrede" value="herr"> Herr</label>
<label><input type="radio" name="anrede" value="frau"> Frau</label>
<label><input type="radio" name="anrede" value="divers"> Divers</label>
</fieldset>
<!-- Flexiblere Gruppierung ohne fieldset -->
<div class="radio-group">
<h3>Bevorzugte Kontaktzeit</h3>
<input type="radio" name="kontaktzeit" value="morgens" data-grouplabel="Kontaktzeit" id="zeit_morgens">
<label for="zeit_morgens">Morgens (8-12 Uhr)</label>
<input type="radio" name="kontaktzeit" value="nachmittags" id="zeit_nachmittags">
<label for="zeit_nachmittags">Nachmittags (12-18 Uhr)</label>
<input type="radio" name="kontaktzeit" value="abends" id="zeit_abends">
<label for="zeit_abends">Abends (18-22 Uhr)</label>
</div>
<fieldset>
<legend>Interessensgebiete</legend>
<label><input type="checkbox" name="interessen[]" value="webdev"> Webentwicklung</label>
<label><input type="checkbox" name="interessen[]" value="design"> Design</label>
<label><input type="checkbox" name="interessen[]" value="seo"> SEO</label>
<label><input type="checkbox" name="interessen[]" value="marketing"> Marketing</label>
</fieldset>
<!-- Multiselect-Alternative -->
<label for="skills">Ihre Fähigkeiten</label>
<select multiple name="skills[]" id="skills">
<option value="php">PHP</option>
<option value="javascript">JavaScript</option>
<option value="css">CSS</option>
<option value="mysql">MySQL</option>
</select>
<?php
$uploadFormHtml = '
<form method="post" enctype="multipart/form-data">
<label for="cv">Lebenslauf (PDF)</label>
<input type="file" id="cv" name="cv" accept=".pdf" required>
<label for="portfolio">Portfolio-Dateien</label>
<input type="file" id="portfolio" name="portfolio[]" multiple accept=".pdf,.jpg,.png">
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
<button type="submit">Bewerbung senden</button>
</form>';
$processor = new FormProcessor(
$uploadFormHtml,
'bewerbung_form',
['pdf', 'jpg', 'jpeg', 'png'], // Erlaubte Dateitypen
10 * 1024 * 1024, // 10 MB Limit
'media/uploads/bewerbungen/' // Upload-Verzeichnis
);
$processor->setEmailFrom('[email protected]');
$processor->setEmailTo('[email protected]');
$processor->setEmailSubject('Neue Bewerbung eingegangen');
?>
<?php
// Moderne Token-Generierung
$timestamp = time();
$token = hash('sha256', $timestamp . session_id() . $_SERVER['REMOTE_ADDR']);
$secureFormHtml = '
<form method="post" enctype="multipart/form-data">
<!-- Spam-Schutz-Felder (werden nicht in E-Mail gesendet) -->
<input type="hidden" name="form_token" value="' . $token . '" data-dontsend>
<input type="hidden" name="form_timestamp" value="' . $timestamp . '" data-dontsend>
<!-- Honeypot für Bots -->
<div style="position: absolute; left: -9999px;" aria-hidden="true">
<label for="website">Website (bitte leer lassen)</label>
<input type="url" id="website" name="website" data-dontsend tabindex="-1" autocomplete="off">
</div>
<!-- Echte Formularfelder -->
<label for="name">Ihr Name</label>
<input type="text" id="name" name="name" required>
<label for="email">E-Mail</label>
<input type="email" id="email" name="email" required>
<fieldset>
<legend>Grund der Anfrage</legend>
<label><input type="radio" name="grund" value="info" data-grouplabel="Anfrageart"> Information</label>
<label><input type="radio" name="grund" value="support"> Support</label>
<label><input type="radio" name="grund" value="verkauf"> Verkauf</label>
</fieldset>
<label>
Nachricht:
<textarea name="nachricht" rows="5" required></textarea>
</label>
<button type="submit">Nachricht senden</button>
</form>';
$processor = new FormProcessor($secureFormHtml, 'secure_contact');
$processor->setEmailFrom('[email protected]');
$processor->setEmailTo('[email protected]');
$processor->setEmailSubject('Sichere Kontaktanfrage');
$processor->setReplyToField('email');
// Spam-Validierung mit modernen Match-Expressions
$isSpam = match (true) {
!empty($_POST['website']) => true, // Honeypot gefüllt
isset($_POST['form_timestamp']) && (time() - (int)$_POST['form_timestamp'] < 3) => true, // Zu schnell
isset($_POST['form_token']) && $_POST['form_token'] !== hash('sha256', $_POST['form_timestamp'] . session_id() . $_SERVER['REMOTE_ADDR']) => true, // Falscher Token
default => false
};
if (!$isSpam) {
$result = $processor->processForm();
// Verarbeitung...
} else {
echo '<div class="error">Spam erkannt. Bitte versuchen Sie es erneut.</div>';
$processor->displayForm();
}
?>
<?php
$modernFormHtml = '
<form method="post" enctype="multipart/form-data" class="uk-form-stacked">
<div class="uk-margin">
<label class="uk-form-label" for="company">Unternehmen</label>
<div class="uk-form-controls">
<input class="uk-input" type="text" id="company" name="company" required>
</div>
</div>
<div class="uk-margin">
<fieldset class="uk-fieldset">
<legend class="uk-legend">Unternehmensgröße</legend>
<div class="uk-form-controls uk-form-controls-text">
<label><input class="uk-radio" type="radio" name="groesse" value="startup"> Startup (1-10)</label><br>
<label><input class="uk-radio" type="radio" name="groesse" value="klein"> Klein (11-50)</label><br>
<label><input class="uk-radio" type="radio" name="groesse" value="mittel"> Mittel (51-250)</label><br>
<label><input class="uk-radio" type="radio" name="groesse" value="gross"> Groß (250+)</label>
</div>
</fieldset>
</div>
<div class="uk-margin">
<fieldset class="uk-fieldset">
<legend class="uk-legend">Benötigte Services</legend>
<div class="uk-form-controls uk-form-controls-text">
<label><input class="uk-checkbox" type="checkbox" name="services[]" value="webdev"> Webentwicklung</label><br>
<label><input class="uk-checkbox" type="checkbox" name="services[]" value="design"> Design</label><br>
<label><input class="uk-checkbox" type="checkbox" name="services[]" value="hosting"> Hosting</label><br>
<label><input class="uk-checkbox" type="checkbox" name="services[]" value="seo"> SEO</label>
</div>
</fieldset>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="budget">Budget</label>
<div class="uk-form-controls">
<select class="uk-select" id="budget" name="budget" required>
<option value="">Bitte wählen</option>
<option value="unter_5k">Unter 5.000 €</option>
<option value="5k_15k">5.000 - 15.000 €</option>
<option value="15k_50k">15.000 - 50.000 €</option>
<option value="ueber_50k">Über 50.000 €</option>
</select>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="dokumente">Projekt-Dokumente</label>
<div class="uk-form-controls">
<input type="file" id="dokumente" name="dokumente[]" multiple accept=".pdf,.doc,.docx">
<div class="uk-text-small uk-text-muted">PDF, DOC, DOCX - max. 10 MB pro Datei</div>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="beschreibung">Projektbeschreibung</label>
<div class="uk-form-controls">
<textarea class="uk-textarea" id="beschreibung" name="beschreibung" rows="5" required></textarea>
</div>
</div>
<div class="uk-margin">
<label><input class="uk-checkbox" type="checkbox" name="newsletter" value="ja"> Newsletter abonnieren</label>
</div>
<div class="uk-margin">
<button class="uk-button uk-button-primary" type="submit">Projektanfrage senden</button>
</div>
</form>';
$processor = new FormProcessor($modernFormHtml, 'projekt_anfrage');
$processor->setEmailFrom('[email protected]');
$processor->setEmailTo('[email protected]');
$processor->setEmailSubject('Neue Projektanfrage');
?>
$processor = new FormProcessor(
$formHtml,
'upload_form',
['pdf', 'doc', 'docx', 'jpg', 'png', 'gif'], // Erlaubte Dateitypen
20 * 1024 * 1024, // 20 MB Limit
'media/uploads/custom/' // Custom Upload-Pfad
);
// Erweiterte E-Mail-Konfiguration
$processor->setEmailFrom('[email protected]');
$processor->setEmailTo('[email protected]');
$processor->setEmailSubject('Upload-Formular: Neue Einreichung');
$processor->setReplyToField('customer_email');
// Formular nur nach CAPTCHA oder Login anzeigen
if (!rex_session('form_access_granted', 'boolean', false)) {
echo '<div class="uk-alert uk-alert-warning">
<p>Bitte lösen Sie zuerst das CAPTCHA.</p>
<form method="post">
<!-- CAPTCHA hier einfügen -->
<button type="submit" name="captcha_solved">Weiter zum Formular</button>
</form>
</div>';
exit;
}
// Nach erfolgreichem CAPTCHA
if (isset($_POST['captcha_solved']) && validateCaptcha()) {
rex_set_session('form_access_granted', true);
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
// Debug-Modus für Entwicklung
if (rex::isDebugMode()) {
echo '<pre>Form Fields: ';
print_r($processor->getProcessedFormData());
echo '</pre>';
echo '<pre>Uploaded Files: ';
print_r($processor->getUploadedFiles());
echo '</pre>';
}
// Custom Error-Handling
if ($result === false) {
$errors = $processor->getErrors(); // Custom Method
foreach ($errors as $error) {
rex_logger::logError('Form Error', $error);
}
}
// PHP 8.4+ nutzt moderne CSS-Selektoren für bessere Performance:
// Vorher (XPath): ~2.5ms
$xpath->query('//input[@type="radio"][@name="field"][@data-grouplabel]')
// Nachher (CSS): ~0.8ms
$dom->querySelector('input[type="radio"][name="field"][data-grouplabel]')
// Massive Performance-Verbesserung bei komplexen Formularen!
- Erfordert PHP >= 8.4 (keine Abwärtskompatibilität)
- Neue DOM Extension muss verfügbar sein
- Legacy-Browser könnten bei sehr modernen HTML5-Features Probleme haben
- Memory Usage bei sehr großen Formularen (>1000 Felder) beachten
// Vor Migration prüfen:
if (version_compare(PHP_VERSION, '8.4.0', '<')) {
throw new Exception('PHP 8.4+ erforderlich für doForm! neo');
}
if (!class_exists('\Dom\HTMLDocument')) {
throw new Exception('Neue DOM Extension nicht verfügbar');
}
// Code kann 1:1 übernommen werden - API ist identisch!
# Installation der neuen DOM Extension
# (meist automatisch mit PHP 8.4+ verfügbar)
sudo apt-get install php8.4-dom
// Für sehr große Formulare (>500 Felder)
ini_set('memory_limit', '256M');
ini_set('max_execution_time', 30);
// UTF-8 wird automatisch erkannt und konvertiert
// Bei persistenten Problemen:
$formHtml = mb_convert_encoding($formHtml, 'UTF-8', 'auto');
// Konstruktor
new FormProcessor(string $formHtml, string $formId, array $allowedExtensions, int $maxFileSize, string $uploadDir)
// Konfiguration
setEmailFrom(string $email): void
setEmailTo(string $email): void
setEmailSubject(string $subject): void
setReplyToField(string $fieldName): void
// Verarbeitung
processForm(): ?bool
displayForm(): void
displayErrors(): void
// Daten abrufen
getProcessedFormData(): array
getUploadedFiles(): array
getFormHtml(): string
Dieses Projekt nutzt die neuesten PHP 8.4+ Features. Beiträge sind willkommen!
# Development Setup
git clone https://github.com/klxm/doform-neo
cd doform-neo
composer install --dev
# Tests ausführen
./vendor/bin/phpunit
MIT License - siehe LICENSE für Details.
- GitHub Issues: Issues
- REDAXO Forum: doForm! neo Support
- Dokumentation: Vollständige Docs
Made with ❤️ for the REDAXO Community
Powered by PHP 8.4+ and modern web standards