I have a search String: $str (Something like "test"), a wrap string: $wrap (Something like "|") and a text string: $text (Something like "This is a test Text").

$str is 1 Time in $text. What i want now is a function that will wrap $str with the wrap defined in $wrap and output the modified text (even if $str is more than one time in $text).

But it shall not output the whole text but just 1-2 of the words before $str and then 1-2 of the words after $str and "..." (Only if it isn`t the first or last word). Also it should be case insensitive.

Example:

$str="Text"$wrap="<span>|</span>"$text="This is a really long Text where the word Text appears about 3 times Text"

Output would be:

"...long <span>Text</span> where...word <span>Text</span> appears...times <span>Text</span>"

My Code (Obviusly doesnt works):

$tempar=preg_split("/$str/i", $text);if (count($tempar) <=2) {$result="... ".substr($tempar[0], -7).$wrap.substr($tempar[1], 7)." ...";} else {$amount=substr_count($text, $str);for ($i=0; $i < $amount; $i++) {$result=$result.".. ".substr($tempar[$i], -7).$wrap.substr($tempar[$i+1], 0, 7)." ..";}}

If you have a tipp or a solution dont hesitate to let me know.

share|improve this question
  • why not $temp=str_replace('|', $str, $wrap); echo str_replace($str, $temp, $text); ?– splash58Feb 13 at 17:25
  • @splash58 that would work but then the thing with the word before and after and with "..." wont work– MilanFeb 13 at 17:31

I have taken your approach and made it more flexible. If $str or $wrap changes you could have escaping issues within the regex pattern so I have used preg_quote.

Note that I added $placeholder to make it clearer, but you can use $placeholder="|" if you don't like [placeholder].

function wrapInString($str, $text, $element='span') {$placeholder="[placeholder]"; // The string that will be replaced by $str$wrap="<{$element}>{$placeholder}</{$element}>"; // Dynamic string that can handle more than just span$strExp=preg_quote($str, '/');$matches=[];$matchCount=preg_match_all("/(\w+\s+)?(\w+\s+)?({$strExp})(\s+\w+)?(\s+\w+)?/i", $text, $matches);$response='';for ($i=0; $i < $matchCount; $i++) {if (strlen($matches[1][$i])) {$response .='...';}if (strlen($matches[2][$i])) {$response .=$matches[2][$i];}$response .=str_replace($placeholder, $matches[3][$i], $wrap);if (strlen($matches[4][$i])) {$response .=$matches[4][$i];}if (strlen($matches[5][$i]) && $i==$matchCount - 1) {$response .='...';}}return $response;}$text="text This is a really long Text where the word Text appears about 3 times Text";string(107) "<span>text</span> This...long <span>text</span> where...<span>text</span> appears...times <span>text</span>"

To make the replacement case insensitive you can use the i regex option.

share|improve this answer
  • Thanks that works great, but do you have an idea how to do the thing:"But it shall not output the whole text but just 1-2 of the words before $str and then 1-2 of the words after $str and "..." (Only if it isn`t the first or last word)."– MilanFeb 13 at 17:41
  • And how do you make this caseinsensitive? Example: If $str is "Text" not only every "Text" will be wrapped but every "text" or "TeXt" ... too.– MilanFeb 13 at 17:52
  • I've updated the question to make it case insensitive.– Jim WrightFeb 13 at 18:28
  • Also updated to include ....– Jim WrightFeb 13 at 19:24
  • Thank you so much dude, its working perfectly!– MilanFeb 14 at 10:08

If I understand your question correct, just a little bit of implode and explode magic needed

$text="This is a really long Text where the word Text appears about 3 times Text";$arr=explode("Text", $text);print_r(implode('&lt;span&gt;Text&lt;/span&gt;', $arr));

If you specifically need to render the span tags using HTML, just write it that way

$arr=explode("Text", $text);print_r(implode('<span>Text</span>', $arr));
share|improve this answer
  • Thanks, but what if the Text contains "test" in lowercase but $str is uppercase("Test")?– MilanFeb 13 at 17:30
  • Just replace the required variables in the explode and implode functions. Assign variable names if required $arr=explode($findVar, $text) and implode($replaceText, $arr)– AdityaFeb 13 at 17:34

Use patern below to get your word and 1-2 words before and after

/((\w+\s+){1,2}|^)text((\s+\w+){1,2}|$)/i

demo

In PHP code it can be:

 $str="Text";$wrap="<span>|</span>";$text="This is a really long Text where the word Text appears about 3 times Text";$temp=str_replace('|', $str, $wrap); // <span>Text</span>// find patern and 1-2 words before and after // (to make it casesensitive, delete 'i' from patern)if(preg_match_all('/((\w+\s+){1,2}|^)text((\s+\w+){1,2}|$)/i', $text, $match)) {$res=array_map(function($x) use($str, $temp) { return '... '.str_replace($str, $temp, $x) . ' ...';}, $match[0]);echo implode(' ', $res);}
share|improve this answer

    Your Answer

     
    discard

    By posting your answer, you agree to the privacy policy and terms of service.

    Not the answer you're looking for? Browse other questions tagged or ask your own question.