PHP: Regular expression to match and replace multiple instances of multiple duplicate matches
P粉738248522
P粉738248522 2024-04-04 15:41:01
0
1
589

I'm looking to write a shortcode system for a gaming community/database where users can add something like ((Magical Sword)) to their content and it will be parsed as Beautiful links to related items with inline thumbnails.

This is the code I'm using so far:

function inlineItems($text) {
    $re = "/\(\(([^)]+)\)\)/m";
    preg_match_all($re, $text, $matches, PREG_SET_ORDER, 0);
    foreach($matches as $match) {
        $slug = makeSlug($match[1]);
        $item = getItem($slug);
        if($item) {
            $text = preg_replace($match[0], '<a class="text-item" data-tooltip="tooltip-item-' . $item->slug . '" href="/items/' . $item->slug .'"><img src="/images/items/' . $item->slug .'.png">' . $item->name .'</a>', $text);
        }
    }
    $text = str_replace("((", "", $text);
    $text = str_replace("))", "", $text);
    return $text;
}

Example output, if the user entered ((Crystal Sword)) would be:

<a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png">Crystal Sword</a>

So far so good, so good.

However, problems arise when a specific match is repeated multiple times within a text string.

If the user enters something like: A ((Crystal Sword)) is crucial for farming, get one ((Crystal Sword)) as soon as possible. ((Crystal Sword)) is the best! Then replace multiple matching project names, and you will end up with this confusion:

<a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png"></a><a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png"></a><a class="text-item" data-tooltip="tooltip-item-crystal-sword" href="/items/crystal-sword"><img src="/images/items/crystal-sword.png">Crystal Sword</a>

How to prevent it from overlapping matches like this?

P粉738248522
P粉738248522

reply all(1)
P粉465675962

Your code is quite confusing. You don't need all of these replacements, one is enough. Follow the KISS principle:

slug}' href='/items/{$item->slug}'>
            
            {$item->name}
        ";

    }, $text);

}


print inlineItems('A ((Crystal Sword)) is essential for farming, get a ((Crystal Sword)) as soon as you can. ((Crystal Sword)) is the best!');
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template