Benutzereingaben enthalten oft HTML-Code, der auf einer Webseite Probleme verursachen kann. Die PHP-Funktion strip_tags() entfernt HTML- und PHP-Tags aus einem String und liefert reinen Text zurück. Das ist nützlich, wenn du Eingaben bereinigen oder Textauszüge ohne Formatierung anzeigen willst. In diesem Tutorial lernst du die Grundlagen, typische Stolperfallen und sichere Alternativen für komplexere Anforderungen.
Syntax und Grundlagen
strip_tags() erwartet einen String und gibt ihn ohne HTML- und PHP-Tags zurück. Über einen optionalen zweiten Parameter lässt sich festlegen, welche Tags erhalten bleiben sollen:
<?php
/* Alle Tags entfernen */
$html = "<h1>Titel</h1><p>Text</p>";
echo strip_tags($html);
// Ausgabe: TitelText
/* Bestimmte Tags behalten */
echo strip_tags($html, '<p>');
// Ausgabe: Titel<p>Text</p>
?>
Ohne zweiten Parameter werden alle Tags restlos entfernt. Beachte, dass der Text aus dem <h1>- und dem <p>-Tag ohne Leerzeichen zusammengefügt wird. Dieses Whitespace-Problem behandeln wir gleich im nächsten Abschnitt.
Das Whitespace-Problem beim Entfernen von Tags
strip_tags() entfernt nur die Tags selbst und fügt keinen Whitespace ein. Bei Block-Elementen wie <p>, <div> oder <li> führt das zu unlesbarem Text ohne Abstände:
<?php
$html = "<p>Erster Absatz.</p><p>Zweiter Absatz.</p>";
echo strip_tags($html);
// Ausgabe: Erster Absatz.Zweiter Absatz.
?>
Die Lösung: Vor dem Aufruf von strip_tags() die schließenden Block-Tags durch ein Leerzeichen ersetzen:
<?php
$html = "<p>Absatz 1.</p><p>Absatz 2.</p>";
$blockTags = [
'</p>', '</div>', '</li>',
'</h1>', '</h2>', '</h3>',
'<br>', '<br/>', '<br />'
];
$html = str_replace($blockTags, ' ', $html);
$text = strip_tags($html);
/* Doppelte Leerzeichen bereinigen */
$text = preg_replace('/\s+/', ' ', trim($text));
echo $text;
// Ausgabe: Absatz 1. Absatz 2.
?>
Dieses Pattern solltest du immer verwenden, wenn du Fließtext aus HTML extrahierst, zum Beispiel für Suchergebnisse oder Teaser-Texte.
Erlaubte Tags als Array (ab PHP 7.4)
Seit PHP 7.4 kann der zweite Parameter auch ein Array sein. Das ist übersichtlicher als ein langer String mit aneinandergereihten Tags. Die erlaubten Tags lassen sich bei Bedarf auch mit der implode()-Funktion dynamisch zusammenbauen:
<?php
$html = "<h1>Titel</h1>";
$html .= "<p>Ein <strong>wichtiger</strong> Text.</p>";
/* Vor PHP 7.4: String-Syntax */
$alt = strip_tags($html, '<p><strong>');
/* Ab PHP 7.4: Array-Syntax */
$neu = strip_tags($html, ['p', 'strong']);
echo $neu;
// Ausgabe: Titel<p>Ein <strong>wichtiger</strong> Text.</p>
?>
Bei der Array-Syntax werden die Tag-Namen ohne spitze Klammern angegeben. Self-Closing Tags wie <br/> oder <img/> werden genauso behandelt: strip_tags($html, '<br>') erlaubt sowohl <br> als auch <br/>.
Sicherheitshinweis: Attribute werden nicht entfernt
strip_tags() entfernt zwar Tags, aber nicht deren Attribute. Wer bestimmte Tags erlaubt, erlaubt damit automatisch auch alle Attribute dieser Tags. Das kann gefährlich werden:
<?php
$eingabe = '<a href="javascript:alert(1)">Klick</a>';
/* Tag bleibt mit gefährlichem Attribut */
$bereinigt = strip_tags($eingabe, ['a']);
echo $bereinigt;
/* Ausgabe: <a href="javascript:alert(1)">Klick</a>
Der JavaScript-Link bleibt erhalten! */
?>
Wenn du erlaubte Tags brauchst und gleichzeitig Attribute kontrollieren willst, reicht strip_tags() allein nicht aus. Im folgenden Abschnitt zeigen wir eine sichere Alternative mit DOMDocument.
DOMDocument: Tags erlauben und Attribute kontrollieren
Mit der PHP-Klasse DOMDocument kannst du erlaubte Tags behalten und gleichzeitig deren Attribute kontrollieren. Das folgende Beispiel erlaubt nur <a>-Tags mit href-Attribut und entfernt alles andere wie onclick oder style:
<?php
function cleanHtml(
string $html,
array $allowed
): string {
$dom = new DOMDocument();
$dom->loadHTML(
'<meta charset="UTF-8">' . $html,
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//*') as $node) {
$tag = strtolower($node->nodeName);
if (!isset($allowed[$tag])) {
/* Tag nicht erlaubt: Textinhalt behalten */
$text = $dom->createTextNode(
$node->textContent
);
$node->parentNode->replaceChild(
$text, $node
);
continue;
}
/* Nur erlaubte Attribute behalten */
$ok = $allowed[$tag];
$len = $node->attributes->length;
for ($i = $len - 1; $i >= 0; $i--) {
$name = $node->attributes->item($i)->name;
if (!in_array($name, $ok, true)) {
$node->removeAttribute($name);
}
}
}
return $dom->saveHTML();
}
$eingabe = '<a href="seite.html" onclick="hack()">';
$eingabe .= 'Link</a>';
$erlaubt = ['a' => ['href'], 'strong' => []];
echo cleanHtml($eingabe, $erlaubt);
/* Ausgabe: <a href="seite.html">Link</a>
onclick wurde entfernt! */
?>
Diese Lösung ist deutlich sicherer als strip_tags() mit erlaubten Tags, weil sie gezielt kontrolliert, welche Attribute bestehen bleiben dürfen.
Vorsicht: script- und style-Inhalte bleiben als Text
strip_tags() entfernt nur die Tags selbst, nicht deren Inhalt. Bei <script>- und <style>-Blöcken bleibt der komplette Code als sichtbarer Text bestehen:
<?php
$html = '<style>body { color: red }</style>';
$html .= '<script>alert("XSS")</script>';
$html .= '<p>Normaler Text</p>';
echo strip_tags($html);
/* Ausgabe:
body { color: red }alert("XSS")Normaler Text */
?>
Der CSS- und JavaScript-Code wird als normaler Text ausgegeben. Um das zu vermeiden, kannst du vor strip_tags() die <script>- und <style>-Blöcke komplett entfernen:
<?php
function stripTagsClean(string $html): string
{
/* script- und style-Blöcke entfernen */
$html = preg_replace(
'~<(script|style)[^>]*>.*?</\\1>~is',
'',
$html
);
return strip_tags($html);
}
$html = '<style>body { color: red }</style>';
$html .= '<script>alert("XSS")</script>';
$html .= '<p>Normaler Text</p>';
echo stripTagsClean($html);
// Ausgabe: Normaler Text
?>
Gerade bei HTML-Inhalten aus externen Quellen oder aus einem WYSIWYG-Editor sollte diese Bereinigung vor strip_tags() laufen.
Praxis: Benutzerkommentare bereinigen
Ein typischer Anwendungsfall ist die Anzeige von Benutzerkommentaren. Dabei willst du meist allen HTML-Code entfernen und den Text zusätzlich mit htmlspecialchars() absichern:
<?php
$kommentar = $_POST['kommentar'] ?? '';
/* Erst Tags entfernen, dann Sonderzeichen
für die HTML-Ausgabe schützen */
$sauber = htmlspecialchars(
strip_tags($kommentar),
ENT_QUOTES,
'UTF-8'
);
echo "<p>" . nl2br($sauber) . "</p>";
?>
Die Kombination aus strip_tags() und htmlspecialchars() ist sicherer als strip_tags() allein. strip_tags() entfernt die Tags, und htmlspecialchars() wandelt verbleibende Sonderzeichen wie &, < und > in HTML-Entities um. Mehr dazu im Tutorial HTML-Zeichen in sichere Zeichen umwandeln.
Textauszug ohne HTML erstellen
Wer auf einer Übersichtsseite einen kurzen Auszug aus einem längeren HTML-Text anzeigen will, kann strip_tags() nutzen. In Kombination mit dem Whitespace-Fix von oben ergibt das saubere Ergebnisse:
<?php
$artikel = "<h2>Überschrift</h2>
<p>Dies ist der erste Absatz mit
etwas mehr Text.</p>
<p>Zweiter Absatz mit Details.</p>";
/* Block-Tags durch Leerzeichen ersetzen */
$text = str_replace(
['</p>', '</div>', '</h2>'],
' ',
$artikel
);
$text = strip_tags($text);
$text = preg_replace('/\s+/', ' ', trim($text));
/* Auf 100 Zeichen kürzen, am Wortende */
if (mb_strlen($text) > 100) {
$text = mb_substr($text, 0, 100);
$text = mb_substr(
$text, 0,
mb_strrpos($text, ' ')
);
$text .= '…';
}
echo "<p>" . htmlspecialchars($text) . "</p>";
?>
Dieser Ansatz eignet sich gut für Blog-Vorschauen, Suchergebnisse oder Teaser-Texte.
strip_tags() auf Arrays anwenden
strip_tags() verarbeitet nur Strings. Für ein ganzes Array bietet sich array_map() an. Du kannst damit alle Elemente in einem Durchgang bereinigen, ohne eine foreach-Schleife zu schreiben:
<?php
$eingaben = [
'<strong>Fett</strong>',
'<em>Kursiv</em>',
'Normaler Text',
];
$bereinigt = array_map('strip_tags', $eingaben);
print_r($bereinigt);
/*
Array
(
[0] => Fett
[1] => Kursiv
[2] => Normaler Text
)
*/
?>
Für eine gründlichere Bereinigung kombiniere strip_tags() mit htmlentities() oder nutze die weiter oben gezeigte stripTagsClean()-Funktion.
Fehlerhaftes HTML und Randfälle
strip_tags() arbeitet mit einem einfachen Parser, der mit fehlerhaftem HTML nicht immer zuverlässig umgehen kann. Hier einige Randfälle, die du kennen solltest:
<?php
/* Offene Tags: werden trotzdem entfernt */
echo strip_tags('<p>Text ohne End-Tag');
// Ausgabe: Text ohne End-Tag
/* HTML-Kommentare: werden entfernt */
echo strip_tags('Vorher<!-- Kommentar -->Nachher');
// Ausgabe: VorherNachher
/* Spitze Klammern in normalem Text */
echo strip_tags('5 < 10 und 20 > 15');
// Ausgabe: 5 15
/* "< 10 und 20 >" wird als Tag interpretiert
und entfernt! */
?>
Das letzte Beispiel zeigt eine wichtige Einschränkung: Wenn normaler Text spitze Klammern enthält, kann strip_tags() diesen fälschlich als Tag erkennen und entfernen. Deshalb sollte Benutzer-Input vor der Einbettung in HTML immer mit htmlspecialchars() behandelt werden.
strip_tags() vs htmlspecialchars()
Beide Funktionen schützen vor HTML-Injection, aber auf unterschiedliche Weise:
strip_tags() entfernt Tags komplett. Der Text innerhalb der Tags bleibt als Klartext erhalten. Das ist die richtige Wahl, wenn du reinen Text ohne jede Formatierung brauchst.
htmlspecialchars() wandelt Sonderzeichen in HTML-Entities um. Die Tags werden sichtbar als Text angezeigt, statt interpretiert zu werden. Das ist besser geeignet, wenn du Code-Beispiele anzeigen willst.
<?php
$html = "<strong>Wichtig</strong>";
echo strip_tags($html);
// Ausgabe: Wichtig
echo htmlspecialchars($html);
/* Ausgabe: <strong>Wichtig</strong>
Im Browser sichtbar als:
<strong>Wichtig</strong> */
?>
Für Benutzereingaben ist die Kombination beider Funktionen am sichersten: Erst strip_tags() zum Entfernen unerwünschter Tags, dann htmlspecialchars() für die sichere Ausgabe.
HTML Purifier: Die professionelle Lösung
Für Projekte, in denen Benutzer eingeschränktes HTML verwenden dürfen (zum Beispiel in einem Blog oder Forum), ist HTML Purifier die zuverlässigste Lösung. Die Bibliothek validiert nicht nur Tags, sondern auch Attribute, CSS-Eigenschaften und URI-Schemata:
<?php
/* Installation per Composer:
composer require ezyang/htmlpurifier */
require 'vendor/autoload.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'p,a[href],strong,em');
$purifier = new HTMLPurifier($config);
$eingabe = '<a href="javascript:alert(1)">';
$eingabe .= 'Link</a>';
$sauber = $purifier->purify($eingabe);
echo $sauber;
/* Ausgabe: <a>Link</a>
Das gefährliche href wurde entfernt! */
?>
Im Gegensatz zu strip_tags() erkennt HTML Purifier auch verschachtelte Angriffsvektoren und validiert Attribute gegen eine Whitelist. Für einfache Fälle reicht strip_tags() mit htmlspecialchars(), aber sobald Benutzer HTML eingeben dürfen, sollte HTML Purifier die erste Wahl sein.