preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead

Dragosius

Erfahrenes Mitglied
Hallo,

ich habe vor einiger Zeit eine alte PHP-Software übernommen, die nur für PHP5 erstellt wurde.
Ich habe sie nun größtenteils auf PHP7 angepasst, hänge hier nur aktuell noch an folgendem Fehler:

preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead

Hier ist die entsprechende Funktion:

PHP:
function unhtmlentities($string) {
    // replace numeric entities
    $string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
    $string = preg_replace('~&#([0-9]+);~e', 'chr("\\1")', $string);
    // replace literal entities
    $trans_tbl = get_html_translation_table(HTML_ENTITIES);
    $trans_tbl = array_flip($trans_tbl);
 
    return strtr($string, $trans_tbl);
}

Der Fehler ist in den Zeilen 3 und 4.

Vielen Dank
 
Zuletzt bearbeitet:
Ich hätte mir einen Vorschlag zur Lösung des Problems gewünscht.
Ich denke, da hätte man durchaus drauf kommen können. ;-)
Wofür gibt es dieses Thema denn dann eigentlich, wenn zu allen Themen, wo man irgendwas über die Suche findet, nicht helfen möchte?

Wäre folgende Lösung für das Zeile 4 dann korrekt?

PHP:
$str = preg_replace_callback(
    "~&#x([0-9a-f]+);~ei",
    function($matches){
        foreach($matches as $match){
            return chr(hexdec($match));
        }
    },
    $str
);
 
Nicht ganz, sieh dir mal $matches mit var_dump an, dann erkennst Du, dass $matches[0] den gesamten Treffer enthält und $matches[1] nur den Bestandteil in Klammern, und nur letzteren willst Du ja ersetzen:
Code:
$str = 'oqiorhhj�oiwrhjh�oiwrhjh';
$str = preg_replace_callback(
    "~&#x([0-9a-f]+);~i",
    function ($matches) {
        var_dump($matches);
        return chr(hexdec($matches[1]));
    },
    $str
);
var_dump($str);
Tritt das Muster mehrmals auf, wird auch die Callback-Funktion mehrmals aufgerufen.
 
Ich möchte fast behaupten, dass der Code unter diesem Link nicht zu Ende gedacht ist:
  • Weil der Teil in Klammern gleich dem gesamten ist, ist $matches[0] gleich $matches[1].
  • Weil im Schleifenkörper ein return steht, wird die Funktion gleich beim ersten Durchlauf verlassen und die Schleife ist wirkungslos.
  • Weil die Aufzählung [a-z] von einem Stern gefolgt wird, liefert sie auch für einen leeren String einen Treffer, wodurch die Callback-Funktion für jeden Treffer zwei Mal aufgerufen wird, beim zweiten Mal mit Leerstrings als Parameter.
 
Eine Verständnisfrage habe ich noch:

Warum hast du in Zeile nur "~i" und nicht "~ei" verwendet?
Gibt es dafür einen Grund?
 
Also würde der Fall für den Code in Zeile 4 aus meinem 1. Beitrag dann so aussehen?

PHP:
$str = 'oqiorhhj�oiwrhjh�oiwrhjh';
$str = preg_replace_callback(
    "~&#([0-9]+)",
    function ($matches) {
        var_dump($matches);
        return chr($matches[1]);
    },
    $str
);
var_dump($str);
 
Ohne es zu testen sehe ich schon, dass da die schließende Tilde und das Semikolon fehlen:
Code:
"~&#([0-9]+);~",
Zum Verständnis: Normaler Weise wird eine Regex von Schrägstrichen eingeschlossen, so:
Code:
"/&#([0-9]+);/",
Man kann jedoch davon abweichen und ein anderes Zeichen verwenden. Das kann sinnvoll sein, wenn in der Regex der Schrägstrich verwendet wird ohne dass er als Delimiter interpretiert werden soll, dann braucht man ihn nicht durch einen Backslash zu maskieren. Da das bei deinen beiden Beispielen nicht der Fall ist, wäre es besser, die gewohnte Version mit Schrägstrichen zu verwenden.
 
Zurück