Funktion mb_substr_count() - Strings zählen in UTF-8

In manchen Fällen wird in PHP-Anwendungen die Information benötigt, wie oft ein Teil-String in einer Zeichenkette enthalten ist. Das kann beispielsweise notwendig sein, wenn man prüfen möchte, ob eine E-Mailadresse nur einmal das Zeichen @ enthält. Um die Teil-Strings zählen zu lassen, kann man die Funktion substr_count() verwenden. Der Nachteil bei dieser Funktion ist, dass bei Multibyte-Zeichen wie den Umlauten oder anderen Zeichen in der Zeichenkodierung UTF-8 die Zählung nicht genau ist, da genau genommen mit den Bytes gearbeitet wird, die die Zeichen belegen.

Im folgenden Beispielcode sollte der Rückgabewert eigentlich 1 sein, da die Zählung mit dem fünften Zeichen beginnen sollte (Position 4). Das ist jedoch nicht der Fall. Da die ersten beiden Zeichen bereits 4 Bytes belegen und die Zählung mit dem dritten Zeichen beginnt, ist der Rückgabewert 3 und nicht 1.

<?php

$str = 'ßßßßß';
$needle = 'ß';
$offset = 4;

// Ausgabe 3
echo substr_count($str, $needle, $offset);

?>

Wenn man in Verbindung mit der Zeichenkodierung UTF-8 auf solche Unstimmigkeiten stößt, kann man statt substr_count() die Multibyte-Funktion mb_substr_count() nutzen. Hierbei ist es möglich, die verwendete Zeichenkodierung anzugeben. Die Parameter werden wie folgt angegeben.

  1. Der String, in der ein Teil-String gezählt werden soll (haystack).
  2. Der Teil-String, der gezählt werden soll (needle).
  3. Die Zeichenkodierung (encoding, optional).

Im folgenden PHP-Code wird im String das Zeichen Ü gezält.

<?php

$str = 'ÜÜÜÜÜ';
$needle = 'Ü';

// Ausgabe 5
echo mb_substr_count($str, $needle, 'UTF-8');

?>

In der Funktion substr_count() wird mit dem 3. Parameter offset festgelegt, wie viele Zeichen zu Beginn übersprungen und für die Zählung nicht berücksichtigt werden sollen. Mit dem 4. Parameter length kann außerdem die maximal zu berücksichtigende Anzahl an Zeichen ab offset festgelegt werden. Die Angabe der Parameter offset oder length ist bei mb_substr_count() leider nicht vorgesehen (Stand Sept. 2016). Das kann sich in Zukunft natürlich ändern. Falls man offset oder length benötigt, kann man eine eigene Funktion schreiben. Im folgenden Code wird dazu die Funktion mb_substr_count_new() erstellt.

<?php

function mb_substr_count_new
(
$str, 
$needle, 
$offset = 0, 
$length = null, 
$encoding = 'UTF-8'
)

{
  return mb_substr_count(
    mb_substr($str, $offset, $length, $encoding), $needle, $encoding);
}

$str = 'ÜÜÜÜÜ';
$needle = 'Ü';
$offset = 2;
$length = 2;

// Ausgabe 2
echo mb_substr_count_new($str, $needle, $offset, $length);

?>

In dem Beispiel sorgt mb_substr() dafür, dass die ersten beiden Zeichen für die Zählung nicht berücksichtigt werden und die maximale Anzahl der zu berücksichtigenden Zeichen ab offset auf 2 begrenzt wird.

In diesem Beispiel ist die Zeichenkodierung standardmäßig auf UTF-8 gesetzt, sodass bei einer Nichtangabe dieser Wert verwendet wird. Normalerweise wird in der Funktion mb_substr_count() jedoch bei einer Nichtangabe die interne Zeichenkodierung verwendet. Falls diese unbekannt ist, kann man den Rückgabewert der Funktion mb_internal_encoding() ausgeben lassen.

<?php

echo mb_internal_encoding();

?>

Für eine Änderung der internen Zeichenkodierung ist eine Anpassung der Konfigurationsdatei php.ini notwendig. Hierbei gibt es mehrere Möglichkeiten. Ab der PHP-Version 5.6 ist der Eintrag default_charset vorgesehen. Es ist auch möglich, den Eintrag mbstring.internal_encoding anzupassen, der ab PHP 5.6 jedoch als deprecated gilt.

Um die Multibyte-Funktionen verwenden zu können, muss auf dem Server die Erweiterung mbstring verfügbar sein. Die Verfügbarkeit kann mit der Funktion phpinfo() ermittelt werden. Die unterstützten Zeichenkodierungen können mit mb_list_encodings() festgestellt werden. Als Rückgabewert erhält man ein Array, den man mit einer foreach-Schleife oder anderen Funktionen wie beispielsweise print_r() auslesen kann.