在 PHP 中将纯文本 URL 转换为 HTML 超链接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1960461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 04:26:58  来源:igfitidea点击:

Convert plain text URLs into HTML hyperlinks in PHP

phpregexhyperlinkpreg-replace

提问by Volomike

I have a simple commenting system where people can submit hyperlinks inside the plain text field. When I display these records back from the database and into the web page, what RegExp in PHP can I use to convert these links into HTML-type anchor links?

我有一个简单的评论系统,人们可以在其中提交纯文本字段内的超链接。当我将这些记录从数据库返回并显示到网页中时,我可以使用 PHP 中的什么 RegExp 将这些链接转换为 HTML 类型的锚链接?

I don't want the algorithm to do this with any other kind of link, just http and https.

我不希望算法使用任何其他类型的链接来执行此操作,仅使用 http 和 https。

回答by RUDD3R

Here is an other solution, This will catch all http/https/www and convert to clickable links.

这是另一个解决方案,这将捕获所有 http/https/www 并转换为可点击的链接。

$url = '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i'; 
$string = preg_replace($url, '<a href="
$url = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/';   
$string= preg_replace($url, '<a href="
$url = '@(http)?(s)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '<a href="http://" target="_blank" title="
$url = '@(http(s)?)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '<a href="http://" target="_blank" title="
$email = '<a href="mailto:[email protected]">[email protected]</a>';
$string = $email;
echo $string;
">
public static function makeClickableLinks($s) {
  return preg_replace('@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', '<a href="" target="_blank"></a>', $s);
}
</a>', $string); echo $string;
">
<?
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]");
?>
</a>', $string); echo $string;
" target="_blank" title="
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", "</a>", $ret);
    $ret = trim($ret);
    return $ret;
}
">
public static function replaceLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?)@', '<a href=""></a>', $s);
}
</a>', $string); echo $string;
" target="_blank" title="
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="
public static function makeClickableLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@', '<a href=""></a>', $s);
}
" style="font-weight: normal;" target="_blank" title="
$s = preg_replace ( 
    "/(?<!a href=\")(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/i",
    "<a href=\"\0\" target=\"blank\">\0</a>",
    $s
);
">
// $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;
}
</a>', $text); //Catch all links without protocol $reg2 = '/(?<=\s|\A)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\.)/'; $formatText = preg_replace($reg2, '<a href="//##代码##" style="font-weight: normal;" target="_blank" title="##代码##">##代码##</a>', $formatText); //Catch all emails $emailRegex = '/(\S+\@\S+\.\S+)\b/'; $formatText = preg_replace($emailRegex, '<a href="mailto:" style="font-weight: normal;" target="_blank" title=""></a>', $formatText); $formatText = nl2br($formatText); return $formatText; }
">##代码##</a>', $string); echo $string;

Alternatively for just catching http/https then use the code below.

或者只是捕获 http/https,然后使用下面的代码。

##代码##

EDIT: The script below will catch all url types and convert them to clickable links.

编辑:下面的脚本将捕获所有 url 类型并将它们转换为可点击的链接。

##代码##

New update, If you're having the string strip the (s) then use the below code block, Thanks to @AndrewEllis for pointing this out.

新更新,如果您将字符串剥离 (s) 然后使用下面的代码块,感谢@AndrewEllis 指出这一点。

##代码##

Here's a very simple solution for the URL not displaying correctly.

这是 URL 无法正确显示的一个非常简单的解决方案。

##代码##

It is a very simple fix but you will have to modify it for your own purpose.

这是一个非常简单的修复,但您必须根据自己的目的对其进行修改。

I've provided multiple answers as some servers are setup differently, so one answer may work for some but not for others, but I hope the answer(s) work for you and if not then let me know and hopefully I can come up with another solution.

由于某些服务器的设置不同,我提供了多个答案,因此一个答案可能适用于某些人,但不适用于其他人,但我希望答案对您有用,如果没有,请告诉我,希望我能想出另一种解决方案。

回答by MkVal

Well, Volomike's answer is much closer. And to push it a bit further, here's what I did for it to disregard the trailing periodat the end of the hyperlinks. I also considered URI fragments.

好吧,Volomike 的答案更接近。为了更进一步,这是我所做的,以忽略超链接末尾的尾随点。我还考虑了 URI 片段。

##代码##

回答by Luca Matteis

##代码##

回答by Ashok Pundit

Refer http://zenverse.net/php-function-to-auto-convert-url-into-hyperlink/. This is how wordpress solve it

请参阅http://zenverse.net/php-function-to-auto-convert-url-into-hyperlink/。这就是 wordpress 解决它的方法

##代码##

回答by Stephan Wagner

The most rated answer didn't do the job for me, following link was not replaced correctly:

评分最高的答案对我不起作用,以下链接未正确替换:

http://www.fifa.com/worldcup/matches/round255951/match=300186487/index.html#nosticky

http://www.fifa.com/worldcup/matches/round255951/match=300186487/index.html#nosticky

After some google searches and some tests, this is what I came up with:

经过一些谷歌搜索和一些测试,这就是我想出的:

##代码##

I'm not an expert in regex, actually it quite confuses me :)

我不是正则表达式的专家,实际上它让我很困惑:)

So feel free to comment and improve this solution.

因此,请随时发表评论并改进此解决方案。

回答by Hoang Trung

Here is my code to format all the links inside text, including emails, urls with and without protocol.

这是我的代码,用于格式化文本中的所有链接,包括电子邮件、带和不带协议的 url。

##代码##

Please comment the url that doesn't work. I'll try to update the regex.

请评论不起作用的网址。我会尝试更新正则表达式。

回答by Volomike

##代码##

回答by Thong Tran

The answer from MkVal works but in the case we already have the anchor link, it will render the text in weird format.

MkVal 的答案有效,但在我们已经有了锚链接的情况下,它将以奇怪的格式呈现文本。

Here is the solution which works for me in both cases:

这是在两种情况下都适用于我的解决方案:

##代码##

回答by Yousf

I recommend not to do many things on fly like this. I prefer to use simple editor interface like the one used in stackoverflow. It is called Markdown.

我建议不要像这样在飞行中做很多事情。我更喜欢使用简单的编辑器界面,比如在 stackoverflow 中使用的界面。它被称为Markdown

回答by Kai Noack

I am using a function that originated from question2answer, it accepts plain text and even plain text links in html:

我正在使用一个源自question2answer的函数,它接受纯文本甚至纯文本的 html 链接:

##代码##

A bit much code due to accepting links that hold brackets and other characters, but probably it helps.

由于接受包含括号和其他字符的链接,代码有点多,但可能会有所帮助。