Sark Sark - 7 months ago 15
PHP Question

PHP: Find substrings, wrap in tags with dynamic attributes

I'm working on a Glossary auto-tooltip function for a site. This will allow the admin to enter Glossary terms with corresponding definitions, then those words will be made into hoverable tooltip triggers anywhere they appear on the front end.

Here's the method I'm using:

All content is filtered before output through a function which searches with a regular expression for glossary terms and wraps them in tags with a class that is then picked up by javascript to handle the hover display of the tooltip.

What I need it to do, and can't figure out, is to also include the appropriate definition as a title attribute on the span.

Here is my code so far: (the initial arrays are just examples, there are many more entries in each)

function glossary_highlight( $content ) {
$glossary = ['Lorem', 'Ipsum'];
$definitions = ['Lorem is a type of crocodile', 'Ipsum is a kitchen utensil'];
$patterns = [];
foreach ($glossary as $term) {
$patterns[] = '/\b' . $term . '\b/i';
}
$wrapper = '<span class="tooltip" title="XXXX">$0</span>';
$wrapped = preg_replace($patterns, $wrapper, $content);
return $wrapped;
}


I need XXXX to be replaced with the appropriate entry in the $definitions array. I can't perform the regular expression within the foreach loop because then it may start adding spans within the titles of other spans if a definition contains another glossary term, etc.

The desired effect - given a $content of "Lorem ipsum dolor sit amet", the return from this function should be:

<span class="tooltip" title="Lorem is a type of crocodile">Lorem</span> <span class="tooltip" title="Ipsum is a kitchen utensil">ipsum</span> dolor sit amet


My first inclination was to do something like:

$wrapper = '<span class="tooltip" title="' . $definitions[$key] . '">$0</span>';


where $key would be relative to the index of the glossary term in question, but I can't figure out how to work that into the foreach.

If I can't figure it all out in PHP I guess I will just apply the tooltip span and send the definition array to javascript to append the title attribute from there, but I'd rather not split the basic task across two languages...

I'm sure there is a totally simple answer here but my brain will not see it! Can anyone help?

EDIT: thanks to lampyridae for his help below the code works as follows:

function glossary_highlight( $content ) {
$glossary = ['Lorem', 'Ipsum'];
$definitions = ['Lorem is a type of crocodile', 'Ipsum is a kitchen utensil'];
$patterns = [];
foreach ($glossary as $term) {
$patterns[] = '/\b' . $term . '\b/i';
}
$wrappers = [];
foreach ($definitions as $definition) {
$wrappers[] = '<span class="tooltip" title="' . $definition . '">$0</span>';
}
$wrapped = preg_replace($patterns, $wrappers, $content);
return $wrapped;
}

Answer

I see two options:

  1. Run preg_replace once for each term. If the texts are long, the terms many and this is done in real time this may become a performance issue.
  2. Supply an array of replacements just as you do for patterns.

I think number 2 would be generally faster and still simple. The idea is to build wrappers like so:

$wrappers = [];
foreach ($definitions as $definition) {
    $wrappers[] = '<span class="tooltip" title="' . $definition . '">$0</span>';
}

…then use the wrappers:

$wrapped = preg_replace($patterns, $wrappers, $content);
Comments