Funktion substr() - Teil eines strings zurückgeben

Es kann manchmal vorkommen, dass man von einer Zeichenkette einen Teil benötigt. Ein typisches Beispiel hierfür ist eine Zeichenkette mit der Postleitzahl und dem Ort. Wenn man nur den Ort benötigt und sicher ist, dass die Postleitzahl 5 Zeichen lang ist und danach ein Leerzeichen folgt, könnte man die ersten 6 Zeichen unberücksichtigt lassen und alle übrigen Zeichen zurückgeben. Für solche Aufgaben gibt in PHP die Funktion substr().

Innerhalb der runden Klammern kann man drei Parameter angeben, wobei der dritte optional ist. Mit dem ersten Parameter übergibt man die Zeichenkette. Der zweite Parameter gibt die Anzahl der Zeichen an, die nicht berücksichtigt werden sollen. Alle übrigen Zeichen ab dieser Stelle werden zurückgegeben. Mit dem optionalen dritten Parameter kann die Zeichenanzahl des Rückgabewerts begrenzt werden. Beim folgenden Beispiel werden die ersten 6 Zeichen nicht berücksichtigt und der Rest zurückgegeben.

<?php

$str = '01234 Musterhausen';

// Ausgabe Musterhausen
echo substr($str, 6);

?>

Beim folgenden Beispiel wurde der dritte Parameter angegeben, mit dem die Zeichenlänge des Rückgabewerts begrenzt wird. In diesem Beispiel wurde als Begrenzung 10 Zeichen angegeben, sodass die Ausgabe Musterhaus ist.

<?php

$str = '01234 Musterhausen';

// Ausgabe Musterhaus
echo substr($str, 6, 10);

?>

Aus technischer Sicht werden nicht die Zeichen des strings an sich berücksichtigt, sondern die Bytes, die diese belegen. Dabei wird davon ausgegangen, dass für jedes Zeichen ein Byte belegt wird. Wenn man z.B. bei einer Zeichenkette mit 10 Zeichen als zweiten Parameter eine 5 angibt und den dritten Parameter ungenutzt lässt, dann werden im Grunde die ersten 5 Bytes unberücksichtigt und der Rest zurückgegeben. Wie viele Bytes ein Zeichen belegt, hängt jedoch von der Zeichenkodierung ab, sodass es vorkommen kann, dass das Ergebnis der Funktion substr() nicht dem entspricht, was man sich vorgestellt hat.

Auswirkung von substr() auf whitespaces

Whitespaces wie Tabulatoren oder Zeilenumbrüche werden in PHP mit einem Backslash \ maskiert, sodass sie in der Zeichenkette mit zwei oder mehr Zeichen geschrieben werden, z.B. als \t oder \n. Sie werden bei der Anwendung der Funktion subtr() wie ein Zeichen behandelt. Beim folgenden Code sind in der Zeichenkette 6 whitespaces und danach die Zeichen ABC. Alle whitespaces bleiben unberücksichtigt, auch wenn die Anzahl der Zeichen hierfür höher ist als 6 und der Rückgabewert ist ABC. Damit die whitespaces als solche erkannt werden, ist die Zeichenkette in Anführungszeichen gesetzt. Verwendet man dagegen einfache Hochkommas, wird ein Backslash \ von PHP nicht als Teil eines whitespace betrachtet.

<?php

$str = " \t\n\r\0\x0BABC";

// Ausgabe ABC
echo substr($str, 6);

?>

Auswirkung von substr() auf Anführungszeichen

Wenn man eine Zeichenkette in einfachen oder doppelten Anführungszeichen setzt, dann muss man diese bei einer Verwendung innerhalb der Zeichenkette ebenfalls mit einem Backslash als \' oder \" maskieren. Wendet man die Funktion substr() auf die Zeichenkette an, werden die maskierten Anführungszeichen wie ein Zeichen behandelt, obwohl sie in der Zeichenkette zwei Zeichen enthalten. Bei den folgenden Codes sind in der Zeichenkette jeweils 5 Anführungszeichen und als Parameter wurde in beiden Fällen 2 angegeben. Die Rückgabewerte enthalten 3 Anführungszeichen.

<?php

$str = '\'\'\'\'\'';

//Ausgabe '''
echo substr($str, 2);

?>
<?php

$str = "\"\"\"\"\"";

// Ausgabe """
echo substr($str, 2);

?>

Auswirkung von substr() auf Entitäten

Manche Sonderzeichen wie <, > oder & haben in HTML und PHP eine spezielle Bedeutung. Sie können in einer Zeichenkette als HTML-Entität geschrieben werden, z.B. &gt; für ein >. Auch für Anführungszeichen oder andere Sonderzeichen gibt es HTML-Entitäten. Wendet man die Funktion substr() auf eine Zeichenkette an, werden die Entitäten nicht wie ein Zeichen behandelt. Stattdessen wird die Anzahl der Zeichen berücksichtigt, mit der eine Entität geschrieben wird.

<?php

$str = '&lt;ABCD';

// Ausgabe ABCD
echo substr($str, 4);


$str = '&gt;ABCD';

// Ausgabe ABCD
echo substr($str, 4);


$str = '&#039;ABCD';

// Ausgabe ABCD
echo substr($str, 6);


$str = '&quot;ABCD';

// Ausgabe ABCD
echo substr($str, 6);

?>

Auswirkung von substr() auf Mehrbyte-Zeichen in UTF-8

Die Zeichenkodierung UTF-8 hat den Vorteil, dass man mehr Zeichen darstellen kann als z.B. mit ASCII oder ANSI. Für die zusätzlichen Zeichen wird mehr Speicherplatz benötigt. So kann es passieren, dass einige Zeichen 2 oder mehr Bytes belegen und daher Mehrbyte-Zeichen genannt werden. Das betrifft vor allem viele Sonderzeichen. Auch Umlaute wie Ä, Ö, Ü oder das ß belegen in UTF-8 zwei Bytes, in ANSI jedoch nur 1 Byte. Da mit substr() im Grunde nur die Anzahl der Bytes herangezogen wird, kann es passieren, dass der Rückgabewert mit UTF-8 nicht dem entspricht, was man sich eigentlich vorgestellt hat.

Beim folgenden Beispiel enthalten die Zeichenketten jeweils 4 Sonderzeichen oder Umlaute, gefolgt von einem Bindestrich und den Zeichen ABCD. Wenn man als Parameter die Zahl 5 angibt, könnte man annehmen, dass der Rückgabewert in allen Fällen ABCD ist. Dem ist jedoch nicht so. Denn, die Sonderzeichen oder Umlaute belegen nicht 4 Bytes, sondern 8. Mit dem Parameter 5 bleiben somit Reste aus den Sonderzeichen und Umlauten übrig, sodass die Ausgabe kryptisch aussehende Zeichen enthält.

<?php

$str = '¡¡¡¡-ABCD';

// Ausgabe ¡Â¡-ABCD
echo substr($str, 5);


$str = '££££-ABCD';

// Ausgabe £Â£-ABCD
echo substr($str, 5);


$str = 'ÄÄÄÄ-ABCD';

// Ausgabe „Ä-ABCD
echo substr($str, 5);


$str = 'ÖÖÖÖ-ABCD';

// Ausgabe –Ö-ABCD
echo substr($str, 5);

?>

Häufig wird versucht, in der PHP-Konfigurationsdatei php.ini die Standardeinstellung für die Zeichenkodierung wie folgt zu setzen und dadurch auf UTF-8 umzustellen.

  • default_charset = "UTF-8"

Eine andere Variante betrifft die .htaccess-Datei mit den folgenden Einstellungen.

  • AddDefaultCharset UTF-8
  • php_value default_charset UTF-8

Manchmal wird auch direkt in der PHP-Datei die Zeichenkodierung festgelegt.

  • header("Content-Type: text/html; charset=utf-8");

Alle drei Lösungen bringen nicht den gewünschten Erfolg. Denn, der Eintrag default_charset in der php.ini dient nur als zentrale Einstellung für Funktionen, bei denen die Angabe der Zeichenkodierung als Parameter möglich ist und ist außerdem erst mit der PHP-Version 5.6 eingeführt worden. Die beiden übrigen Lösungsmöglichkeiten betreffen lediglich die vom Server übermittelte Zeichenkodierung beim Aufruf der Seite.

Die grundsätzliche Funktionsweise von substr(), dass nämlich bei der Bearbeitung die Anzahl der Bytes herangezogen wird und mit UTF-8 viele Zeichen mehr als 1 Byte belegen, bleibt davon unberührt. Beim folgenden Beispiel wurde die Standardeinstellung mit allen drei Möglichkeiten auf UTF-8 umgestellt. Geändert haben sich dabei lediglich die kryptisch aussehenden Zeichen.

<?php

$str = '¡¡¡¡-ABCD';

// Ausgabe �¡-ABCD
echo substr($str, 5);


$str = '££££-ABCD';

// Ausgabe �£-ABCD
echo substr($str, 5);


$str = 'ÄÄÄÄ-ABCD';

// Ausgabe �Ä-ABCD
echo substr($str, 5);


$str = 'ÖÖÖÖ-ABCD';

// Ausgabe �Ö-ABCD
echo substr($str, 5);

?>

Daher ist festzustellen, dass wenn man die Zeichenkodierung UTF-8 verwendet, die Funktion substr() nicht unbedingt geeignet ist, um einen Teil aus einer Zeichenkette zurückgeben zu lassen. Eine Lösungsmöglichkeit kann die Multibyte-Funktion mb_substr() bieten. Diese funktioniert genauso wie substr(), nur mit dem Unterschied, dass auch die Zeichenkodierung beachtet wird. Wenn z.B. ein Zeichen zwei Bytes belegt, so werden beide Bytes einem Zeichen zugeordnet und man erhält bessere Ergebnisse.