Reputation: 13
I'm trying to mimic Twitter's hash tagging system, replacing all hashtags with clickable links. I put together a snippet that works but I discovered that if two words have similar beginnnings, the longer word only gets replaced (by a clickable link) to the length where the shorter word stopped. ie, if I have a sentence '#tool in a #toolbox', #tool becomes a link, and only #tool in #toolbox becomes a link, not the entire #toolbox.
Below is the snippet:
<?php
//define text to use in preg_match and preg_replace
$text = '#tool in a #toolbox';
//get all words with hashtags
preg_match_all("/#\w+/",$text,$words_with_tags);
//if there are words with hash tags
if(!empty($words_with_tags[0])){
$words = $words_with_tags[0];
//define replacements for each tagged word,
// $replacement is an array of replacements for each word
// $words is an array of words to be replaced
for($i = 0; $i < sizeof($words) ; $i++ ){
$replacements[$i] = '<a href="'.trim($words[$i],'#').'">'.$words[$i].'</a>';
// format word as /word/ to be used in preg_replace
$words[$i] = '/'.$words[$i].'/';
}
//return tagged text with old words replaced by clickable links
$tagged_text = preg_replace($words,$replacements,$text);
}else{
//there are no words with tags, assign original text value to $tagged_text
$tagged_text = $text;
}
echo $tagged_text;
?>
Upvotes: 1
Views: 213
Reputation: 12389
What about capturing and doing a simple preg_replace()
$tagged_text = preg_replace('~#(\w+)~', '<a href="\1">\0</a>', $text);
Test at eval.in outputs to:
<a href="tool">#tool</a> in a <a href="toolbox">#toolbox</a>
Upvotes: 1
Reputation: 11365
You can use preg_replace_callback
<?php
$string = "#tool in a #toolbox";
$str = preg_replace_callback(
'/\#[a-z0-9]+/',
function ($matches) {
return "<a href=\"". ltrim($matches[0], "#") ."\">". $matches[0] ."</a>";
}, $string);
echo $str;
//Output: <a href="tool">#tool</a> in a <a href="toolbox">#toolbox</a>
Upvotes: 0