Home > Software design >  String Replace that contains hashtags-php
String Replace that contains hashtags-php

Time:09-16

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

It prints like this

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 &#35; which will be ignored by str_ireplace() and would work properly, like below:

'<a ...>&#35;'.$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).'">&#35;'. $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];
}
  • Related