Search code examples
phpregexpreg-replacepreg-replace-callback

preg_replace with urlencode


I am trying to create hashtag links with preg_replace and I encounter issues when a "" in the hashtag is present. I am not really good at patterns so any help would be appreciated:

My pattern:

$hashtags_url = '/(\#)([x00-\xFF]+[a-zA-Z0-9x00-\xFF_\w]+)/';

$body = preg_replace($hashtags_url, '<a href="'.$hashtag_path.'$2" title="#$2">#$2</a>', $body);

This works perfect to a normal hashtag but the issue is when i try to urlencode the $2 parameter.

I tried

$hashtags_url = '/(\#)([x00-\xFF]+[a-zA-Z0-9x00-\xFF_\w]+[x00-\xFF]+[a-zA-Z0-9x00-\xFF_\w])/';

and

   $body = preg_replace_callback(
$hashtags_url,
function($matches) {
    return "<a href=\"$hashtag_path/hashtag/".urlencode($matches[2])."\">#".
           $matches[2]."</a>";
},
$body);

and it goes well but now the single-worded hashtags are omitted.


Solution

  • You can use the following simplified regex, with $matches[1] to access the hashtag name in the anonymous function used as the replacement argument:

    /#(\S+)/
    

    Make sure you pass all necessary variables using use keyword to the callback function (see use ($hashtag_path)).

    See the PHP demo:

    $body = "Text text #hashtag text text #hast/tag";
    $hashtag_path = '/path/to';
    $hashtags_url = '/#(\S+)/';
    $body = preg_replace_callback(
    $hashtags_url, function($matches) use ($hashtag_path) {
        return "<a href=\"$hashtag_path/hashtag/".urlencode($matches[1])."\">".$matches[0]."</a>";
    },
    $body);
    echo $body;
    

    Output:

    Text text <a href="/path/to/hashtag/hashtag">#hashtag</a> text text <a href="/path/to/hashtag/hast%2Ftag">#hast/tag</a>