URL’s automatisch in klickbare Links umwandeln mit PHP
Man kennt das Phänomen von vielen Internetportalen und Foren, sobald man einen Kommentar abgibt oder etwas postet, was eine URL enthält, wird automatisch ein klickbarer Link daraus generiert. Da dieses Feature ziemlich komfortabel ist, schauen wir uns an, wie wir so etwas selbst programmieren können.
Vorüberlegung
Damit aus einer URL ein anklickbarer HTML Link gemacht wird, muss die URL in entsprechende HTML Tags gesetzt werden. Schauen wir uns dazu folgenden Beispieltext an:
Ich lese gerade ein Tutorial auf http://staticfloat.com, indem gezeigt wird wie man aus URLs klickbare Links generieren kann
Damit http://staticfloat.com klickbar wird, muss der Text folgendermaßen umgewandelt werden:
Ich lese gerade ein Tutorial auf <a href="http://staticfloat.com">http://staticfloat.com</a>, indem gezeigt wird wie man aus URLs klickbare Links generieren kann
Es müssen also URL’s erkannt und daraus HTML Tags generiert werden. URL’s als solche zu erkennen ist jedoch alles andere als ein einfaches unterfangen und bedarf einen komplexen regulären Ausdruck.
URL’s erkennen
Eine URL richtig zu erkennen ist der schwierigste Teil des ganzen Tutorials. Nach ein bisschen Internetrecherche findet man zwar einige regulären Ausdrücke die das Problem vermeintlich lösen, aber eben trotzdem noch einige Gegenbeispiele gefunden werden können, für URL’s die eben nicht gematched werden.
Die Komplexität liegt am Aufbau einer URL, so sind http://www.staticfloat.com, http://staticfloat.com, staticfloat.com, www.staticfloat.com und http://staticfloat.com/index.php alles URL’s von denen wir erwarten, dass sie alle gültig und anklickbar sind.
$regex = '((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)';
Der obenstehende reguläre Ausdruck sieht kompakt aus und würde auch viele URL’s richtig erkennen, aber bereits bei einer URL ohne http:// wäre Schluss (http://www.staticfloat.com match aber www.staticfloat.com no match).
Da wir aber nicht zu viel Zeit mit regulären Ausdrücken in diesem Tutorial verbringen wollen, greifen wir auf einen regulären Ausdruck zurück, mit dem ich bisher noch keine URL gefunden habe die nicht erkannt wird.
URL Pattern
$regex = "/( (?:
(?:https?|ftp) : \\/*
(?:
(?: (?: [a-zA-Z0-9-]{1,} \\. )+
(?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2}
| aero | biz | coop | info | museum | name | pro
| example | invalid | localhost | test | local | onion | swift ) )
| (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} )
| (?: [0-9A-Fa-f:]+ : [0-9A-Fa-f]{1,4} )
)
(?: : [0-9]+ )?
(?! [a-zA-Z0-9.:-] )
(?:
\\/
[^&?#\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]*
)?
(?:
[?#]
[^\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]+
)?
) | (?:
(?:
(?: (?: [a-zA-Z0-9-]{2,} \\. )+
(?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2}
| aero | biz | coop | info | museum | name | pro
| example | invalid | localhost | test | local | onion | swift ) )
| (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} )
)
(?: : [0-9]+ )?
(?! [a-zA-Z0-9.:-] )
(?:
\\/
[^&?#\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]*
)?
(?:
[?#]
[^\\(\\)\\[\\]\\{\\}<>\\'\\\"\\x00-\\x20\\x7F-\\xFF]+
)?
) | (?:
[a-zA-Z0-9._-]{2,} @
(?:
(?: (?: [a-zA-Z0-9-]{2,} \\. )+
(?: arpa | com | org | net | edu | gov | mil | int | [a-z]{2}
| aero | biz | coop | info | museum | name | pro
| example | invalid | localhost | test | local | onion | swift ) )
| (?: [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} \\. [0-9]{1,3} )
)
) )/Dx";
Dieses Muster sieht sehr komplex aus, erkennt aber zuverlässig URL’s, was wir als Grundlage für dieses Tutorials brauchen.
PHP Funktion
Nachdem wir jetzt einen zuverlässigen regulären Ausdruck haben um eine URL zu erkennen, geht es an die eigentliche Funktion. PHP bietet mit der Methode preg_replace_callback() die Möglichkeit, eine Callbackfunktion auf jede gefundene URL anzuwenden. In unserem Fall muss die Callbackfunktion den reinen String der URL in einen a Tag packen, um den Link damit klickbar zu machen.
function linkify($string)
{
// Pattern von oben einfügen.
$regex = '....'
$string = htmlspecialchars($string);
if(!function_exists('valid_url')) {
function valid_url($url)
{
if(substr($url[0], 0, 7) != 'http://') {
$valid_url = 'http://'.$url[0];
} else {
$valid_url = $url[0];
}
return '<a class="link" href="'.$valid_url.'">'.$url[0].'</a>';
}
}
$output = preg_replace_callback($regex, 'valid_url', $string);
return $output;
}
Alternativ kann der reguläre Ausdruck auch als Konstante definiert werden, dann muss man ihn nicht lokal in der Funktion deklarieren. Ob das Sinn macht kommt auf den Anwendungszweck an und sollte man selbst entscheiden.
Verwendung
Die Funktion linkify() bekommt als Parameter einen String übergeben, in dem sämtliche URL’s klickbar (in HTML Links umgewandelt) gemacht werden sollen. Da auf den String bereits htmlspecialchars() angewendet wird, kann man die Daten auch direkt ausgeben.
//.... $comment = $_GET['user_comment']; echo linkify($comment);
Da preg_replace eine relativ aufwändige Operation ist, sollte man darüber nachdenken, ob man nicht gleich die Version mit HTML Links in der Datenbank speichert, statt bei jeder Ausgabe die URL’s in klickbare Links umzuwandeln.
Eine interessante Variante der kursierenden Ausdrücke, die ich noch nicht gesehen habe. Werde ich gelegentlich ausprobieren. Ich benutze seit vielen Jahren für mein CMS eine solche Umwandlung, wenn ich neue Texte eingebe, aber es bleibt folgendes Problem: Sobald schon anklickbare Links im Artikel sind und ich diese Artikel update, gibt es Murks. Daher suchte ich über die Jahre hinweg immer wieder mal nach einer Lösung, die bestehende Links ausklammert. Man könnte meinen, das ist einfach, aber ich suchte jedesmal einige Nächte lang, umsonst. Vor einem Jahr fand ich zufälligerweise ein paar lösungen auf einer amerikanischen Seite, und habe sie mir für spätere Tests vorgemerkt. Leider sind die Bookmarks verloren gegangen. Weißt du zufälligerweise eine Lösung?
Hmm auf die Schnelle würde ich jetzt vorschlagen, zuerst alle a HTML Tags aus dem Text zu entfernen und dann wieder neu generieren zu lassen. Das geht zum Beispiel mit strip_tags.
Hallo,
erstmal: Lebt dein YouTube Kanal noch? :D
Ok jz zum Thema:
Wie muss ich denn ein Comment einfügen, also so das es überhaupt umgewandelt wird.
Muss ich zb eine Variable $con = "Hallo www.youtube.com"; oder sowas angeben?
Weil sonst wird bei mir nix umgewandelt... Wie mache ich das? :D
Gruß
Hi,
du musst normalerweise einfach die Funktion mit einem String aufrufen und fertig.
Zum Youtube-Channel, ja eigentlich sollte der schon noch leben, nur momentan passt es zeitlich einfach nicht.