homepage Welcome to WebmasterWorld Guest from 54.242.18.232
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
WOW . . explain this one!
It's solved, but very odd.
rocknbil




msg:4083295
 3:09 am on Feb 19, 2010 (gmt 0)


Say you have this.

if ($row['price']) { $price = '<p class="' . $settings['price_display'] . '">Price: $' . $row['price'] . '</p>'; }

Note the $ is single quoted, in this context it will not interpolate.

Then the variable $price is used in a substitution in a template, like

$thisTemplate = preg_replace("/\[PRICESTRING\]/",$price,$thisTemplate);

Easy enough. But the prices, say, 300.00, 100.00, etc. - come out in a variety of odd formats:

Price: 0.00
Price: .00

Sure, you say, just escape it. Tried that. Same effect. Changed quoting, changed quoting in the preg pattern from " to ', changed various ways of doing this, all came out wonky. Here's what fixed it:


if ($row['price']) { $price = '<p class="' . $settings['price_display'] . '">Price: \\\\\$' . $row['price'] . '</p>'; }

One escape more or less - it breaks. I **kinda** know what's going on, I just don't know why. When you want to preg_match on \, you need to do

if (preg_match('/\\\\/',$text)) { echo 'you matched on A SINGLE \'; }

So my guess is in the final preg_replace, the $ gets interpolated in the string $price, but to escape it - create one \ so you have \$ - you need FIVE \'s in the original string to get

Price: $100.00

Weirdest thing I've ever seen, has someone got an explanation that won't make my head explode? :-P

 

eelixduppy




msg:4083313
 4:20 am on Feb 19, 2010 (gmt 0)

In the replacement string, $price, you can add a back reference to matched groups of the pattern in the format
\\n where n is the group number. In order to escape the back reference you need to quadruple the backslash: \\\\. Since you also needed to escape the dollar sign, an extra one was needed it seems. Never run into this situation before but it certainly is an interesting one.

I'm going to digest this a bit, though heh

Readie




msg:4083326
 5:05 am on Feb 19, 2010 (gmt 0)

Just a thought... Could 2 of the backslashes be escaping other backslashes for PhP, and the other one escapes the dollar sign leaving you with \\

Then when you call it in the preg_replace, it acts as one backslash escaping another?

Edit:

Blargh, just properly read Eelixpuppy's response - I'm practically saying the same thing dumbed down :/

---

I am curious: does changing the dollar to &#36; completley remove the need for the backslashes?

rocknbil




msg:4083563
 5:49 pm on Feb 19, 2010 (gmt 0)

Haha . . . . yeah I tried that too, it came out as a literal. &#36; 100.00 and %24 100.00.

pinterface




msg:4083787
 3:42 am on Feb 20, 2010 (gmt 0)

When doing a "dumb replace" like that, I find it less confusing to use strtr [us3.php.net]. As in:
$thisTemplate = strtr($thisTemplate, "[PRICESTRING]", $price);
which has the advantage of avoiding multiple levels of string escaping. :)

astupidname




msg:4083799
 5:03 am on Feb 20, 2010 (gmt 0)

$thisTemplate = strtr($thisTemplate, "[PRICESTRING]", $price);

strtr would not work in this context as it goes character by character, when using the 'from' and 'to' parameters, and therefore completely mangles the string in that usage. Should use array instead:
$thisTemplate = strtr($thisTemplate, array('[PRICESTRING]' => $price));

Although what you are really doing is a simple str_replace:
$thisTemplate = str_replace("[PRICESTRING]", $price, $thisTemplate);

strtr is very useful when you have multiple different in-string replacements, but may be simple enough to just use the str_replace

Readie




msg:4083800
 5:04 am on Feb 20, 2010 (gmt 0)

That's as may be Pinterface - but I've thought on this for quite some time and havn't been able to reason why &#36; came out as a literal in this context - as I have preg_replaced numerous &#xx; codes in myself using some scripts, with each of the codes contained within single quotes as rocknbil has above.

astupidname




msg:4083803
 5:17 am on Feb 20, 2010 (gmt 0)

an explanation that won't make my head explode?

And as for that, ummm... would the fact that php is a retarded language (apparently designed by a bunch of dyslexics with a real fetish for the '$' sign -damn them idiots, it just had to get rolled over to javascript too... arghh.. puke...) with flaws like all others make your head explode? Don't get me too wrong, there are some things I really like about php.. :)

jkovar




msg:4083907
 1:42 pm on Feb 20, 2010 (gmt 0)

If you have a $row['price'] that puts a number after the dollar sign you end up with a replacement string that preg_replace could interpret as having a back-reference to the pattern.

You know how preg_replace('#1(2)3#', "middle is $1", $str) would give you "middle is 2" ?

// Edit -- I should probably start reading replies *before* I answer one of these days...

rocknbil




msg:4084024
 8:08 pm on Feb 20, 2010 (gmt 0)

^ ^ ^ RIGHT . . . I think that's it, or something like it. I just couldn't find the words.

A FYI, I duplicated this snippet in Perl "just to see" and lo and behold, no workaround toothpick syndrome escaping required.


#!/usr/bin/perl -w
$price='';
%row = (
'price' => '300.00'
);
if ($row{'price'}) {
$price = '<p>Price: $' . $row{'price'} . '</p>';
}
## For example:
$thisTemplate= qq|
<p>Blah blah</p>
[PRICE]
<p>Blah blah</p>
|;
print "<p>BEFORE:</p>\n\n $thisTemplate";
if ($thisTemplate =~ /\[PRICE\]/) {
$thisTemplate =~ s/\[PRICE\]/$price/g;
}
print "<p>AFTER:</p>\n\n $thisTemplate";


As you'd think . . . it prints $300.00. With or without the quote in the original hash.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved