Преобразование простых текстовых URL-адресов в HTML-гиперссылки на PHP
У меня есть простая система комментариев, в которой люди могут отправлять гиперссылки внутри обычного текстового поля. Когда я отображаю эти записи обратно из базы данных и на веб-страницу, какое регулярное выражение в PHP я могу использовать для преобразования этих ссылок в якорные ссылки HTML-типа?
Я не хочу, чтобы алгоритм делал это с помощью каких-либо других ссылок, только http и https.
13 answers
Вот другое решение, оно будет перехватывать все http/https/www и преобразовывать в интерактивные ссылки.
$url = '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i';
$string = preg_replace($url, '<a href="$0" target="_blank" title="$0">$0</a>', $string);
echo $string;
В качестве альтернативы для простого перехвата http/https используйте приведенный ниже код.
$url = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/';
$string= preg_replace($url, '<a href="$0" target="_blank" title="$0">$0</a>', $string);
echo $string;
РЕДАКТИРОВАТЬ: Приведенный ниже скрипт будет перехватывать все типы URL-адресов и преобразовывать их в интерактивные ссылки.
$url = '@(http)?(s)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '<a href="http$2://$4" target="_blank" title="$0">$0</a>', $string);
echo $string;
Новое обновление, Если вы хотите удалить строку (ы), используйте приведенный ниже блок кода, спасибо @Andrewellis за указание на это.
$url = '@(http(s)?)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '<a href="http$2://$4" target="_blank" title="$0">$0</a>', $string);
echo $string;
Вот очень простое решение для URL-адрес отображается неправильно.
$email = '<a href="mailto:[email protected]">[email protected]</a>';
$string = $email;
echo $string;
Это очень простое исправление, но вам придется изменить его для своих собственных целей.
Что ж, ответ Воломике гораздо ближе. И чтобы продвинуть его немного дальше, вот что я сделал для того, чтобы он игнорировал завершающий период в конце гиперссылок. Я также рассмотрел фрагменты URI.
public static function makeClickableLinks($s) {
return preg_replace('@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', '<a href="$1" target="_blank">$1</a>', $s);
}
<?
function makeClickableLinks($text)
{
$text = html_entity_decode($text);
$text = " ".$text;
$text = eregi_replace('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
'<a href="\\1" target=_blank>\\1</a>', $text);
$text = eregi_replace('(((f|ht){1}tps://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
'<a href="\\1" target=_blank>\\1</a>', $text);
$text = eregi_replace('([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
'\\1<a href="http://\\2" target=_blank>\\2</a>', $text);
$text = eregi_replace('([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})',
'<a href="mailto:\\1" target=_blank>\\1</a>', $text);
return $text;
}
// Example Usage
echo makeClickableLinks("This is a test clickable link: http://www.websewak.com You can also try using an email address like [email protected]");
?>
Ссылка http://zenverse.net/php-function-to-auto-convert-url-into-hyperlink /. Вот как wordpress решает эту проблему
function _make_url_clickable_cb($matches) {
$ret = '';
$url = $matches[2];
if ( empty($url) )
return $matches[0];
// removed trailing [.,;:] from URL
if ( in_array(substr($url, -1), array('.', ',', ';', ':')) === true ) {
$ret = substr($url, -1);
$url = substr($url, 0, strlen($url)-1);
}
return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>" . $ret;
}
function _make_web_ftp_clickable_cb($matches) {
$ret = '';
$dest = $matches[2];
$dest = 'http://' . $dest;
if ( empty($dest) )
return $matches[0];
// removed trailing [,;:] from URL
if ( in_array(substr($dest, -1), array('.', ',', ';', ':')) === true ) {
$ret = substr($dest, -1);
$dest = substr($dest, 0, strlen($dest)-1);
}
return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>" . $ret;
}
function _make_email_clickable_cb($matches) {
$email = $matches[2] . '@' . $matches[3];
return $matches[1] . "<a href=\"mailto:$email\">$email</a>";
}
function make_clickable($ret) {
$ret = ' ' . $ret;
// in testing, using arrays here was found to be faster
$ret = preg_replace_callback('#([\s>])([\w]+?://[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_url_clickable_cb', $ret);
$ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_web_ftp_clickable_cb', $ret);
$ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret);
// this one is not in an array because we need it to run last, for cleanup of accidental links within links
$ret = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $ret);
$ret = trim($ret);
return $ret;
}
Самый рейтинговый ответ не справился со своей задачей за меня, следующая ссылка была неправильно заменена:
Http://www.fifa.com/worldcup/matches/round255951/match=300186487/index.html#nosticky
После некоторых поисков в Google и некоторых тестов вот что я придумал:
public static function replaceLinks($s) {
return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $s);
}
Я не эксперт в регулярных выражениях, на самом деле это меня очень смущает:)
Так что не стесняйтесь комментировать и улучшать это решение.
public static function makeClickableLinks($s) {
return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $s);
}
Вот мой код для форматирования всех ссылок внутри текста, включая электронные письма, URL-адреса с протоколом и без него.
public function formatLinksInText($text)
{
//Catch all links with protocol
$reg = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/\S*)?/';
$formatText = preg_replace($reg, '<a href="$0" style="font-weight: normal;" target="_blank" title="$0">$0</a>', $formatText);
//Catch all links without protocol
$reg2 = '/(?<=\s|\A)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\.)/';
$formatText = preg_replace($reg2, '<a href="//$0" style="font-weight: normal;" target="_blank" title="$0">$0</a>', $formatText);
//Catch all emails
$emailRegex = '/(\S+\@\S+\.\S+)/';
$formatText = preg_replace($emailRegex, '<a href="mailto:$1" style="font-weight: normal;" target="_blank" title="$1">$1</a>', $formatText);
$formatText = nl2br($formatText);
return $formatText;
}
Пожалуйста, прокомментируйте URL-адрес, который не работает. Я постараюсь обновить регулярное выражение.
Я рекомендую не делать много вещей на лету, как это. Я предпочитаю использовать простой интерфейс редактора, подобный тому, который используется в stackoverflow. Это называется Уценка.
Ответ от MkVal работает, но в случае, если у нас уже есть якорная ссылка, она отобразит текст в странном формате.
Вот решение, которое работает для меня в обоих случаях:
$s = preg_replace (
"/(?<!a href=\")(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/i",
"<a href=\"\\0\" target=\"blank\">\\0</a>",
$s
);
Я использую функцию, которая возникла из question2answer, она принимает простой текст и даже простые текстовые ссылки в html:
// $html holds the string
$htmlunlinkeds = array_reverse(preg_split('|<[Aa]\s+[^>]+>.*</[Aa]\s*>|', $html, -1, PREG_SPLIT_OFFSET_CAPTURE)); // start from end so we substitute correctly
foreach ($htmlunlinkeds as $htmlunlinked)
{ // and that we don't detect links inside HTML, e.g. <img src="http://...">
$thishtmluntaggeds = array_reverse(preg_split('/<[^>]*>/', $htmlunlinked[0], -1, PREG_SPLIT_OFFSET_CAPTURE)); // again, start from end
foreach ($thishtmluntaggeds as $thishtmluntagged)
{
$innerhtml = $thishtmluntagged[0];
if(is_numeric(strpos($innerhtml, '://')))
{ // quick test first
$newhtml = qa_html_convert_urls($innerhtml, qa_opt('links_in_new_window'));
$html = substr_replace($html, $newhtml, $htmlunlinked[1]+$thishtmluntagged[1], strlen($innerhtml));
}
}
}
echo $html;
function qa_html_convert_urls($html, $newwindow = false)
/*
Return $html with any URLs converted into links (with nofollow and in a new window if $newwindow).
Closing parentheses/brackets are removed from the link if they don't have a matching opening one. This avoids creating
incorrect URLs from (http://www.question2answer.org) but allow URLs such as http://www.wikipedia.org/Computers_(Software)
*/
{
$uc = 'a-z\x{00a1}-\x{ffff}';
$url_regex = '#\b((?:https?|ftp)://(?:[0-9'.$uc.'][0-9'.$uc.'-]*\.)+['.$uc.']{2,}(?::\d{2,5})?(?:/(?:[^\s<>]*[^\s<>\.])?)?)#iu';
// get matches and their positions
if (preg_match_all($url_regex, $html, $matches, PREG_OFFSET_CAPTURE)) {
$brackets = array(
')' => '(',
'}' => '{',
']' => '[',
);
// loop backwards so we substitute correctly
for ($i = count($matches[1])-1; $i >= 0; $i--) {
$match = $matches[1][$i];
$text_url = $match[0];
$removed = '';
$lastch = substr($text_url, -1);
// exclude bracket from link if no matching bracket
while (array_key_exists($lastch, $brackets)) {
$open_char = $brackets[$lastch];
$num_open = substr_count($text_url, $open_char);
$num_close = substr_count($text_url, $lastch);
if ($num_close == $num_open + 1) {
$text_url = substr($text_url, 0, -1);
$removed = $lastch . $removed;
$lastch = substr($text_url, -1);
}
else
break;
}
$target = $newwindow ? ' target="_blank"' : '';
$replace = '<a href="' . $text_url . '" rel="nofollow"' . $target . '>' . $text_url . '</a>' . $removed;
$html = substr_replace($html, $replace, $match[1], strlen($match[0]));
}
}
return $html;
}
Немного много кода из-за принятия ссылок, содержащих скобки и другие символы, но, вероятно, это помогает.
Попробуйте вот это:
$s = preg_replace('/(?<!href="|">)(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/is', '<a href="\\1" target="_blank">\\1</a>', $s);
Он пропускает существующие ссылки (если у нас уже есть href, он не будет добавлять href внутри href). В противном случае он добавит ссылку a href с пустой целью.
$string = 'example.com
www.example.com
http://example.com
https://example.com
http://www.example.com
https://www.example.com';
preg_match_all('#(\w*://|www\.)[a-z0-9]+(-+[a-z0-9]+)*(\.[a-z0-9]+(-+[a-z0-9]+)*)+(/([^\s()<>;]+\w)?/?)?#i', $string, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach (array_reverse($matches) as $match) {
$a = '<a href="'.(strpos($match[1][0], '/') ? '' : 'http://') . $match[0][0].'">' . $match[0][0] . '</a>';
$string = substr_replace($string, $a, $match[0][1], strlen($match[0][0]));
}
echo $string;
Результат:
example.com
<a href="http://www.example.com">www.example.com</a>
<a href="http://example.com">http://example.com</a>
<a href="https://example.com">https://example.com</a>
<a href="http://www.example.com">http://www.example.com</a>
<a href="https://www.example.com">https://www.example.com</a>
Что мне нравится в этом решении, так это то, что оно также преобразует www.example.com
в http://www.example.com
, потому что <a href="www.example.com"></a>
не работает (без протокола http/https
, на который он указывает yourdomain.com/www.example.com
).
Если я прав, то вы хотите превратить обычный текст в http-ссылки. Вот что, я думаю, может помочь:
<?php
$list = mysqli_query($con,"SELECT * FROM list WHERE name = 'table content'");
while($row2 = mysqli_fetch_array($list)) {
echo "<a target='_blank' href='http://www." . $row2['content']. "'>" . $row2['content']. "</a>";
}
?>