I have a string like this
$content="#Love #Lovestories #Lovewalapyar";
Want to make these hashtags clickable.
I have an array.
$tags=
(
[0] => stdClass Object
(
[TOPIC_ID] => 132
[TOPIC_NAME] => Love
[TOPIC_URL] => http://local/topic/132/love
)
[1] => stdClass Object
(
[TOPIC_ID] => 3347
[TOPIC_NAME] => LoveStories
[TOPIC_URL] => http://local/topic/3347/lovestories
)
[2] => stdClass Object
(
[TOPIC_ID] => 43447
[TOPIC_NAME] => lovewalapyar
[TOPIC_URL] => http://local/topic/43447/lovewalapyar
)
);
Using this to make hashtags clickable.
foreach($tags as $tag){
$content=str_ireplace('#'.$tag->TOPIC_NAME, '<a href="'.$tag->TOPIC_URL.'" title="'.htmlentities($tag->TOPIC_NAME).'">#'.$tag->TOPIC_NAME.'</a>', $content);
}
Getting this: It replaces only love not the other string.
Trying to replace/Make these hashtags clickable.
Any help would be much appriciated.
CodePudding user response:
The reason is simple. You have hashtags which are substrings of other hashtags. To avoid this overlapping issue, you can sort your array in a non-increasing fashion replacing longer strings first and shorter strings later, completely avoid the overlapping issue, like below:
<?php
usort($tags,function($a,$b){
return strlen($b->TOPIC_NAME) <=> strlen($a->TOPIC_NAME);
});
Update:
Your hashtag text inside <a></a>
is causing the str_ireplace
to reconsider it. For this you need to pass the array values and their respective replacements in an array, or, instead of adding a #
, you can use a HTML character entity #
which will be ignored by str_ireplace()
and would work properly, like below:
'<a ...>#'.$tag->TOPIC_NAME.'</a>';
Updated Snippet:
<?php
usort($tags,function($a,$b){
return strlen($b->TOPIC_NAME) <=> strlen($a->TOPIC_NAME);
});
foreach($tags as $tag){
$content = str_ireplace('#'.$tag->TOPIC_NAME, '<a href="'.$tag->TOPIC_URL.'" title="'.htmlentities($tag->TOPIC_NAME).'">#'. $tag->TOPIC_NAME.'</a>', $content);
}
CodePudding user response:
I would use the regular expression /#(\w*)/
(hashtag and whitespace) and preg_replace()
to replace all occurrences.
Something like this:
$content = "#Love #Lovestories #Lovewalapyar";
$pattern = '/#(\w*)/';
$replacement = '<a href="#$1">$1</a>';
preg_replace($pattern, $replacement, $content);
this will give you:
<a href="#Love">Love</a>
<a href="#Lovestories">Lovestories</a>
<a href="#Lovewalapyar">Lovewalapyar</a>
You can test that regex online here.
If you need some advanced logic as Magnus Eriksson mentioned in comments you can use preg_match_all
and iterate over your found matches.
Something like this:
$content = "#Love #Lovestories #Lovewalapyar";
$pattern = '/#(\w*)/';
preg_match_all($pattern, $content, $matches);
foreach ($matches[1] as $key => $match) {
// do whatever you need here, you might want to use $tag = $tags[$key];
}