Voraussetzung ist allerdings, dass der Webserver mod_rewrite unterstützt und dass dies über die .htaccess richtig configuriert ist.

Nun geht es an eine kleine PHP-Funktion.

Nennen wir sie in diesem Beispiel „prettyURL“

1
2
3
4
function prettyURL() {
.....
.....
}

Dieser Funktion müssen natürlich bei Aufruf noch einige Parameter mitgegeben werden. So zum Beispiel der String, also die Wortkette, welche umgewandelt werden soll. Und, otional, ein Trennzeichen, mit dem die einzelnen Wörter getrennt werden sollen.

1
2
3
4
function prettyURL($url, $trenner = '-') {
.....
.....
}

Innerhalb der Funktion werden diese Variablen dann weiterverarbeitet.

1
2
3
4
$var_URL        = trim(utf8_encode($url));  # Uebergebene URL (wird in UTF-8 gewandelt)
$var_worttrenner    = $trenner;         # Uebergebenes Trennzeichen
$var_maxRepeat      = '1';              # Maximale Wiederholungen des Trennzeichens in der URL
$array_patternParts = array();          # Benötigtes Array

Das eingefügte Array wird später noch gebraucht.
Nun benötigen wir ein zweites Array, welches die verschiedenen Sonderzeichen umwandelt in unser Ersatzzeichen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$array_replaceChars = array(
    '/ä/' => 'ae', '/Ä/' => 'ae', '/ö/' => 'oe', '/Ö/' => 'oe', '/ü/' => 'ue', '/Ü/' => 'ue',
    '/(X)HTML/' => 'xhtml', '/(x)html/' => 'xhtml', '/ß/' => 'ss', '/!/' => $var_worttrenner,
    '/\?/' => $var_worttrenner, '/"/' => $var_worttrenner, '/§/' => $var_worttrenner,
    '/\$/' => $var_worttrenner, '/%/' => $var_worttrenner, '/\//' => $var_worttrenner,
    '/\(/' => $var_worttrenner, '/\)/' => $var_worttrenner, '/=/' => $var_worttrenner,
    '/\´/' => $var_worttrenner, '/\`/' => $var_worttrenner, '/\²/' => $var_worttrenner,
    '/\³/' => $var_worttrenner, '/\{/' => $var_worttrenner, '/\[/' => $var_worttrenner,
    '/\]/' => $var_worttrenner, '/\}/' => $var_worttrenner, '/\\\/' => $var_worttrenner,
    '/\@/' => $var_worttrenner, '/€/' => 'euro', '/\*/' => $var_worttrenner, '/\+/' => $var_worttrenner,
    '/\~/' => $var_worttrenner, '/\'/' => $var_worttrenner, '/\#/' => $var_worttrenner,
    '/\<' $var_worttrenner, '/\>/' => $var_worttrenner, '/\|/' => $var_worttrenner,
    '/,/' => $var_worttrenner, '/;/' => $var_worttrenner, '/\./' => $var_worttrenner,
    '/:/' => $var_worttrenner, '/-/' => $var_worttrenner, '/_/' => $var_worttrenner,
    '/ /' => $var_worttrenner, '/«/' => $var_worttrenner, '/»/' => $var_worttrenner,
    '/¢/' => $var_worttrenner, '/„/' => $var_worttrenner, '/“/' => $var_worttrenner,
    '/”/' => $var_worttrenner, '/µ/' => $var_worttrenner, '/·/' => $var_worttrenner,
    '/←/' => $var_worttrenner, '/…/' => $var_worttrenner, '/ĸ/' => $var_worttrenner,
    '/↓/' => $var_worttrenner, '/æ/' => $var_worttrenner, '/ł/' => $var_worttrenner,
    '/→/' => $var_worttrenner, '/ſ/' => $var_worttrenner, '/˝/' => $var_worttrenner,
    '/ø/' => $var_worttrenner, '/ð/' => $var_worttrenner, '/^/' => $var_worttrenner,
    '/þ/' => $var_worttrenner, '/đ/' => $var_worttrenner, '/ł/' => $var_worttrenner,
    '/Æ/' => $var_worttrenner, '/ŋ/' => $var_worttrenner, '/¶/' => $var_worttrenner,
    '/¨/' => $var_worttrenner, '/ħ/' => $var_worttrenner, '/ŧ/' => $var_worttrenner,
    '/˙/' => $var_worttrenner, '/Ω/' => $var_worttrenner, '/¯/' => $var_worttrenner,
    '/¦/' => $var_worttrenner, '/Ł/' => $var_worttrenner, '/Æ/' => $var_worttrenner,
    '/›/' => $var_worttrenner, '/®/' => $var_worttrenner, '/‹/' => $var_worttrenner,
    '/™/' => $var_worttrenner, '/Ŧ/' => $var_worttrenner, '/Ð/' => $var_worttrenner,
    '/©/' => $var_worttrenner, '/¥/' => $var_worttrenner, '/ª/' => $var_worttrenner,
    '/‚/' => $var_worttrenner, '/↑/' => $var_worttrenner, '/Ŋ/' => $var_worttrenner,
    '/‘/' => $var_worttrenner, '/ı/' => $var_worttrenner, '/Ħ/' => $var_worttrenner,
    '/’/' => $var_worttrenner, '/Ø/' => $var_worttrenner, '/Ł/' => $var_worttrenner,
    '/º/' => $var_worttrenner, '/Þ/' => $var_worttrenner, '/×/' => $var_worttrenner,
    '/^/' => $var_worttrenner, '/¨/' => $var_worttrenner, '/÷/' => $var_worttrenner,
);

Damit sollten so ziemlich alle Sonderfälle der deutschen Umgangssprache abgearbeitet sein. Diese werden einfach durch den festgelegten Trenner ersetzt.

1
$var_prettyURL  = preg_replace(array_keys($array_replaceChars), array_values($array_replaceChars), $var_URL);

Nun haben wir einen umgewandelten String, in dem alle Leerzeichen und Sonderfälle aus dem obigem Array ersetzt wurden. Natürlich kann es nun vorkommen, dass mehrere der Trennzeichen aufeinander folgen, was unschön aussieht.

1
2
3
4
5
foreach (str_split($var_worttrenner) as $var_char) {
    $array_patternParts[]   = sprintf('%s{%d,}', $var_char, $var_maxRepeat);
}

$var_prettyURL  = preg_replace_callback(sprintf('/%s/i', join('|', $array_patternParts)), create_function('$matches', 'return $matches[0][0];'), $var_prettyURL);

Damit wäre diese nun herausgefiltert.
Als Letztes kommt noch ein wenig Feinschliff. Unnötige Zeichen vor und nach unserer URL werden nun entfernt. Also, sowas wie eventuelle Leerzeichen oder Trennzeichen an Anfang und Ende. Gleichzeitig sorgen wir dafür, dass alles klein geschrieben und die umgewandelte URL aus der Funktion an den Aufruf zurück gegeben wird.

1
2
3
4
5
6
7
8
9
10
11
12
$var_prettyURL  = strtolower($var_prettyURL);
$var_prettyURL  = trim($var_prettyURL);

if ($var_prettyURL{substr($var_prettyURL, 0, 1)} == $var_worttrenner) {
    $var_prettyURL  = substr($var_prettyURL, 1);
}

if ($var_prettyURL{strlen($var_prettyURL)-1} == $var_worttrenner) {
    $var_prettyURL  = substr($var_prettyURL, 0, -1);
}

return $var_prettyURL;

Aufgerufen wird die Funktion dann wie folgt:

1
2
$string     = 'Dies ist ein Testfall für eine umgewandelte URL';
echo prettyURL($string);

Wie hier zu sehen ist, wird auf die zweite Option verzichtet. Ist dies der Fall, wird einfach ein ‚-‚ als Trenner eingesetzt.
Die Ausgabe des obigen Beispieles wäre dann:

dies-ist-ein-testfall-fuer-eine-umgewandelte-url

Viel Spaß damit.

Artikel / Seite weiterempfehlen

3 Meinungen zu “String in lesbare URL umwandeln

  1. Hallo Peter,

    vielen Dank für dein hilfreiches Tutorial.

    Ich bekomme allerdings folgende Fehlermeldung:

    Warning: preg_replace_callback() [function.preg-replace-callback]: Compilation failed: nothing to repeat at offset 3

    Kannst du mir weiterhelfen?

    Vielen Dank für deine Hilfe

    Gruß

  2. Vielen Dank für Deine Anleitung! Die hat mir den Einstieg in die Problematik erleichtert.

    Nachdem ich mir jetzt meine eigene Funktion zusammengestellt habe, habe ich ein paar Verbesserungsvorschläge. Da die Vorschläge nicht nur einen Teil Deiner Funktion betreffen, würde ich gerne meine komplette Funktion beschreiben.
    Der Funktionsname und die Variablen heißen bei mir alle etwas anders.

    Zur Erläuterung der Zwischenstände definiere ich mal eine Zeichenkette die von der Funktion umgewandelt wird:

    | -Hello world! -Hallöle Welt! -Allô le monde |

    Die Pipe-Symbole (|) am Anfang und am Ende gehören nicht zur Zeichenkette. Sie dienen nur zur Begrenzung, damit man auch die Leerzeichen am Anfang und am Ende sieht.

    1
    2
    3
    function format_url_label($label, $separator = '-')
    {
        $label = strtolower(trim($label));

    Zunächst werden alle Leerzeichen, Tabs usw. am Anfang und am Ende entfernt und alle Zeichen in Kleinbuchstaben umgewandelt.
    Die Codierung nach UTF-8 geschieht bei mir außerhalb der Funktion. So kann die Funktion flexibler genutzt werden.

    Das Beispiel sieht hier nun so aus:

    |-hello world! -hallöle welt! -allô le monde|

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        $label = str_replace(
            array(
                'ä',
                'ö',
                'ü',
                'ß'
            ),
            array(
                'ae',
                'oe',
                'ue',
                'ss'
            ),
            $label
        );

    Die einfachen Ersetzungen erledigt str_replace(), weil das bei solchen einfachen Sachen in der Regel schneller ist als preg_replace().
    Hier könnten noch weitere einfache Ersetzungen vorgenommen werden (zum Beispiel Dein „(x)html“ nach „xhtml“).
    Da die Zeichenkette hier bereits in Kleinschreibung vorliegt, müssen auch die Ersetzungen nur in Kleinbuchstaben definiert werden.

    Nachdem str_replace() seine Arbeit erledigt hat, sind die deutschen Umlaute sauber ersetzt und die Zeichenkette sieht so aus:

    |-hello world! -halloele welt! -allô le monde|

    Jetzt können wir die grobe Keule für die weiteren Ersetzungen auspacken.

    1
    2
    3
    4
    5
        $replacements = array(
            '/[^0-9a-z]/' => $separator,
            '/'.$separator.'{2,}/' => $separator,
        );
        $label = preg_replace(array_keys($replacements), $replacements, $label);

    Im ersten Schritt werden ALLE Zeichen gegen das Trennzeichen ersetzt, die nicht im Bereich 0 – 9 und a – z liegen.
    Das erspart einem die Arbeit, selbst die Definition der zu ersetzenden Zeichen zu pflegen und hat den Vorteil, dass auch die Zeichen berücksichtigt werden die man vergessen hat.
    Das Ergebnis sieht so aus:

    |-hello-world—halloele-welt—all-le-monde|

    (Als Franzose hätte man vielleicht noch die Ersetzung „ô“ -> „o“ gemacht)

    Der zweite reguläre Ausdruck sorgt dafür, dass jedes Auftreten von zwei oder mehr zusammenhängenden Trennzeichen durch ein einzelnes Trennzeichen ersetzt wird.
    Und das Ergebnis:

    |-hello-world-halloele-welt-all-le-monde|

    Nachdem die Ersetzungen durchgeführt wurden, müsste unsere Zeichenkette folgende Eigenschaften haben:
    – nur Kleinbuchstaben,
    – keine Leerzeichen usw. am Anfang und am Ende der Zeichenkette,
    – nur Zeichen von 0 – 9, von a – z sowie das gewünschte Trennzeichen innerhalb der Zeichenkette,
    – keine mehrfaches Auftreten des Trennzeichens in der Zeichenkette.

    Das Einzige was die Zeichenkette jetzt noch verunstalten könnte, wären Trennzeichen am Anfang und am Ende.

    1
    2
    3
    4
    5
    6
        if ($label[0] == $separator) {
            $label  = substr($label, 1);
        }
        if ($label[strlen($label) - 1] == $separator) {
            $label  = substr($label, 0, -1);
        }

    Der Zugriff auf den Anfang der Zeichenkette erfolgt wie bei bei einem Array, einfach durch Angabe des Index 0. Wird hier ein Trennzeichen gefunden, dann wird es entfernt. Anschließend wird dann noch das Ende der Zeichenkette überprüft und ebenso behandelt.

    Das Ergebnis ist das was wir haben wollen:

    |hello-world-halloele-welt-all-le-mond|

    Die Schreibweise mit den geschweiften Klammern ($label{0}) ist übrigens nicht zu empfehlen, weil die irgendwann nicht mehr funktionieren wird (ich habe mal gelesen, dass diskutiert wurde die in PHP 6 zu entfernen).

    Zum Schluss wir die fertige Zeichenkette dann nur noch zurückgegeben.

    1
    2
        return $label;
    }

    Viele Grüße.

    Bill

Schreibe einen Kommentar

Ihre Email-Adresse wird nicht veröffentlicht. Pflichtfelder sind durch * markiert.

Sie können folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>