Reputation: 67
This code belongs to a search function. A user can enter $search_string and the code below will put html around the string to highlight it. Search has been expanded to include multi-word searches (if you search 'ifs ands' it will only show results with both of those words).
It searches through an array of arrays and the nested array contain fields that we search through: Overview, procedure and verification. It then finds the values in the array and highlights the words you've searched for.
foreach ($results as $s_result => $row) {
$results[$s_result]['overview'] = str_ireplace($search_string, "<span style=\"background-color: #ff0;\">$search_string</span>", htmlspecialchars($row['overview']));
$results[$s_result]['execution'] = str_ireplace($search_string, "<span style=\"background-color: #ff0;\">$search_string</span>", htmlspecialchars($row['execution']));
$results[$s_result]['verification'] = str_ireplace($search_string, "<span style=\"background-color: #ff0;\">$search_string</span>", htmlspecialchars($row['verification']));
}
WITHOUT having to iterate through the array of arrays multiple times for each search keyword, how can I highlight multiple words/keywords the user enters in one pass? There might not be a way but I cant easily come to that conclusion.
Upvotes: 0
Views: 97
Reputation: 42694
str_replace
can take an array as a subject so this should work:
foreach ($results as &$row) {
$row = str_ireplace(
$search_string,
"<span class=\"highlight\">$search_string</span>",
array_map("htmlspecialchars", $row)
);
}
Note we’re changing $row
by reference, so when you iterate over $results
it will show the changes.
Of course you’re not accounting for substrings and such, so a regular expression might be better suited for this:
foreach ($results as &$row) {
$row = preg_replace(
"/\\b($search_string)\\b/i",
"<span class=\"highlight\">$1</span>",
array_map("htmlspecialchars", $row)
);
}
Finally, if you really want to get rid of the foreach
loop you can use array_walk
with an inline function, although I'm not sure how much faster it actually is – it's quite possible it uses the same calls as a foreach
loop when you get down to the C code.
array_walk($results, function(&$v, $k) use($search_string) {
$v = preg_replace(
"/\\b($search_string)\\b/i",
"<span class=\"highlight\">$1</span>",
array_map("htmlspecialchars", $v)
);
});
Tested with sample input:
$search_string = "foobar";
$results = [
["overview"=>"some fobar text", "execution"=>"some foobr text", "verification"=>"some foobar text"],
["overview"=>"some fbar text", "execution"=>"some fobr text", "verification"=>"some foobarbaz text"],
];
Upvotes: 1