Convert plain text URLs into HTML hyperlinks in PH

2019-01-04 00:09发布

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?

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

13条回答
Luminary・发光体
2楼-- · 2019-01-04 00:48

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 period at the end of the hyperlinks. I also considered URI fragments.

public static function makeClickableLinks($s) {
  return preg_replace('@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', '<a href="$1" target="_blank">$1</a>', $s);
}
查看更多
别忘想泡老子
3楼-- · 2019-01-04 00:48

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

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;
}

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

查看更多
The star\"
4楼-- · 2019-01-04 00:49

I am using a function that originated from question2answer, it accepts plain text and even plain text links in 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;
}

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

查看更多
孤傲高冷的网名
5楼-- · 2019-01-04 00:51
public static function makeClickableLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $s);
}
查看更多
看我几分像从前
6楼-- · 2019-01-04 00:51

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.

查看更多
ら.Afraid
7楼-- · 2019-01-04 00:51

If am right, what you want to do is turn ordinary text into http links. Here's what I think can help:

<?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>";

   }  
?>
查看更多
登录 后发表回答