PHP Связывание ссылок в контенте

Я работаю над небольшим проектом, и я нахожусь в положении, когда мне нужна функция php, которая может связывать URL-адреса в моих данных, позволяя мне устанавливать некоторые исключения для ссылок, которые я не хочу связывать. Любая идея, как это сделать?

У меня есть проект с открытым исходным кодом на GitHub: LinkifyURL, который вы можете рассмотреть. Он имеет функцию: linkify() которая выгружает URL-адреса из текста и преобразует их в ссылки. Обратите внимание, что это не тривиальная задача, чтобы сделать правильно! (См .: Проблема с URL-адресами – и обязательно прочитайте поток комментариев, чтобы понять все, что может пойти не так.)

Если вам действительно НЕ нужно связывать определенные домены (например, vimeo и youtube), здесь есть модифицированная функция PHP linkify_filtered (в виде рабочего тестового скрипта), которая делает то, что вам нужно:

 <?php // test.php 20110313_1200 function linkify_filtered($text) { $url_pattern = '/# Rev:20100913_0900 github.com\/jmrware\/LinkifyURL # Match http & ftp URL that is not already linkified. # Alternative 1: URL delimited by (parentheses). (\() # $1 "(" start delimiter. ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $2: URL. (\)) # $3: ")" end delimiter. | # Alternative 2: URL delimited by [square brackets]. (\[) # $4: "[" start delimiter. ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $5: URL. (\]) # $6: "]" end delimiter. | # Alternative 3: URL delimited by {curly braces}. (\{) # $7: "{" start delimiter. ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $8: URL. (\}) # $9: "}" end delimiter. | # Alternative 4: URL delimited by <angle brackets>. (<|&(?:lt|\#60|\#x3c);) # $10: "<" start delimiter (or HTML entity). ((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]+) # $11: URL. (>|&(?:gt|\#62|\#x3e);) # $12: ">" end delimiter (or HTML entity). | # Alternative 5: URL not delimited by (), [], {} or <>. ( # $13: Prefix proving URL not already linked. (?: ^ # Can be a beginning of line or string, or | [^=\s\'"\]] # a non-"=", non-quote, non-"]", followed by ) \s*[\'"]? # optional whitespace and optional quote; | [^=\s]\s+ # or... a non-equals sign followed by whitespace. ) # End $13. Non-prelinkified-proof prefix. ( \b # $14: Other non-delimited URL. (?:ht|f)tps?:\/\/ # Required literal http, https, ftp or ftps prefix. [a-z0-9\-._~!$\'()*+,;=:\/?#[\]@%]+ # All URI chars except "&" (normal*). (?: # Either on a "&" or at the end of URI. (?! # Allow a "&" char only if not start of an... &(?:gt|\#0*62|\#x0*3e); # HTML ">" entity, or | &(?:amp|apos|quot|\#0*3[49]|\#x0*2[27]); # a [&\'"] entity if [.!&\',:?;]? # followed by optional punctuation then (?:[^a-z0-9\-._~!$&\'()*+,;=:\/?#[\]@%]|$) # a non-URI char or EOS. ) & # If neg-assertion true, match "&" (special). [a-z0-9\-._~!$\'()*+,;=:\/?#[\]@%]* # More non-& URI chars (normal*). )* # Unroll-the-loop (special normal*)*. [a-z0-9\-_~$()*+=\/#[\]@%] # Last char can\'t be [.!&\',;:?] ) # End $14. Other non-delimited URL. /imx'; // $url_replace = '$1$4$7$10$13<a href="$2$5$8$11$14">$2$5$8$11$14</a>$3$6$9$12'; // return preg_replace($url_pattern, $url_replace, $text); $url_replace = '_linkify_filter_callback'; return preg_replace_callback($url_pattern, $url_replace, $text); } function _linkify_filter_callback($m) { // Filter out youtube and vimeo domains. $pre = $m[1].$m[4].$m[7].$m[10].$m[13]; $url = $m[2].$m[5].$m[8].$m[11].$m[14]; $post = $m[3].$m[6].$m[9].$m[12]; if (preg_match('/\b(?:youtube|vimeo)\.com\b/', $url)) { return $pre . $url . $post; } // else linkify... return $pre .'<a href="'. $url .'">' . $url .'</a>' .$post; } // Create some test data. $data = 'Plain URLs (not delimited): foo http://example.com bar... foo http://example.com:80 bar... foo http://example.com:80/path/ bar... foo http://example.com:80/path/file.txt bar... foo http://example.com:80/path/file.txt?query=val&var2=val2 bar... foo http://example.com:80/path/file.txt?query=val&var2=val2#fragment bar... foo http://example.com/(file\'s_name.txt) bar... (with \' and (parentheses)) foo http://[2001:0db8:85a3:08d3:1319:8a2e:0370:7348] bar... ([IPv6 literal]) foo http://[2001:0db8:85a3:08d3:1319:8a2e:0370:7348]/file.txt bar... ([IPv6] with path) foo http://youtube.com bar... foo http://youtube.com:80 bar... foo http://youtube.com:80/path/ bar... foo http://youtube.com:80/path/file.txt bar... foo http://youtube.com:80/path/file.txt?query=val&var2=val2 bar... foo http://youtube.com:80/path/file.txt?query=val&var2=val2#fragment bar... foo http://youtube.com/(file\'s_name.txt) bar... (with \' and (parentheses)) foo http://vimeo.com bar... foo http://vimeo.com:80 bar... foo http://vimeo.com:80/path/ bar... foo http://vimeo.com:80/path/file.txt bar... foo http://vimeo.com:80/path/file.txt?query=val&var2=val2 bar... foo http://vimeo.com:80/path/file.txt?query=val&var2=val2#fragment bar... foo http://vimeo.com/(file\'s_name.txt) bar... (with \' and (parentheses)) '; // Verify it works... echo(linkify_filtered($data) ."\n"); ?> 

Для выполнения фильтрации используется функция обратного вызова. Да, регулярное выражение сложное (но это проблема, как выясняется!). Вы можете увидеть интерактивную версию linkify() в JavaScript здесь: URL Linkification (HTTP / FTP) .

Кроме того, у Джона Грубера довольно хорошее регулярное выражение, чтобы сделать привязку. См. «Улучшенный либеральный, точный шаблон регулярного выражения для сопоставления URL-адресов» . Однако при определенных обстоятельствах его регулярное выражение страдает от катастрофического отступления . (Я написал ему об этом, но он еще не ответил).

Надеюсь это поможет! 🙂

Ну, это вполне нормально, но есть еще огромная проблема, существующие якоря внутри строки, я хотел бы привязать текст, не превращая их в бессмысленную часть sh.t.

 $string = "some text and a link http://www.google.com" $new_string = ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]","<a href=\"\\0\">\\0</a>", $string) 

или использовать:

http://code.iamcal.com/php/lib_autolink/