tags:

views:

35

answers:

2

Consider the following situation: I want to replace links in a string, specifically I want to add a "search engine" link next to it.

Think: Link Title (S), where as S will link to Google with "Link Title" as search term. I've copied a real life example string ($content) in the code so you can reproduce this 1:1 in PHP code.

// PCRE case-insensitive, all as a single string, ungreedy and evaluate PHP replace.
$content = '<h3 class="bgg2" style="padding: 4px 0px 4px 5px; font-size: 11px;">» <a href="/forum_detail.html?topic=3456&amp;start=20&amp;post=97145#p97145" class="nub" title="Xenoblade: Japanischer TV-Spot"><b>Xenoblade: Japanischer TV-Spot</b></a></h3>';

$replace = preg_replace('/(<a.*>)(.*)<\/a>/isUe', ('"\1\2</a>&nbsp;(<a href=\"http://www.google.com/search?q=' . strip_tags(strtoupper('blah\2')) . '\">S</a>)"'), $content);

print($replace);

Output (incorrect): Xenoblade: Japanischer TV-Spot (S) -> when you look at the HTML it looks like this:

<a href="http://www.google.com/search?q=BLAH%3Cb%3EXenoblade:%20Japanischer%20TV-Spot%3C/b%3E"&gt;S&lt;/a&gt;

The strtoupper() did get the literal string blah -> BLAH but not the \2 back reference from the regular expression?

It looks like the \2 back referenced string is used BEFORE strtoupper() or strip_tags() functions are executed - some kind of timing of evaluation versus functions in PHP perhaps?

Does anybody know how to explain this bevhaviour?

--

I've developed a workaround using preg_replace_callback, still I'm puzzled about why the above code doesn't work as I expected.

For reference to see what I want to achive:

Solution

// I have to use PHP < 5.0 so create_function() will do the job.
$replace = preg_replace_callback('/(<a.*>)(.*)<\/a>/isU',
create_function('$matches', 'return $matches[1] . $matches[2] . \'</a>&nbsp;(<a href="http://www.google.com/search?q=\' . strip_tags(strtoupper($matches[2])) . \'">S</a>)\';'),
$content);

print($replace);

Output (correct): Xenoblade: Japanischer TV-Spot (S) -> when you look at the HTML it looks like this:

<a href="http://www.google.com/search?q=XENOBLADE:%20JAPANISCHER%20TV-SPOT"&gt;S&lt;/a&gt;

+1  A: 

I think your mixing up a few things. In your first to try you called strtoupper(), which works on the passed string. It will take the string 'blah\2' and turn it into 'BLAH\2'. It's not working on the result, but on your replacement pattern. It's as if you wrote...

'"\1\2</a>&nbsp;(<a href=\"http://www.google.com/search?q='  
 . strip_tags('BLAH\2') . '\">S</a>)"'

as replacement pattern.

Simon
+2  A: 

Change

'"\1\2</a>&nbsp;(<a href=\"http://www.google.com/search?q=' . strip_tags(strtoupper('blah\2')) . '\">S</a>)"'

to

'"\1\2</a>&nbsp;(<a href=\"http://www.google.com/search?q=" . strip_tags(strtoupper(\'blah\2\')) . "\">S</a>)"'

The strip_tags() function needs to be a part of the replacement string so it doesn't get evaluated before it gets passed to preg_replace().

BipedalShark
I've tested this and confirmed it as an excellent solution.Thanks!
capfu