How to escape ampersand in PHP?

I know just enough about PHP to be dangerous. I am good with HTML and I do web design for a PHP programmer. So of course there are times when the HTML and the PHP have to play nicely together.

I’m also a stickler when it comes to web standards compliance.

The problem is that any page containing links with the “&” sign will not validate. I know you can just change the & to &, but I don’t always have access to the code that creates the links; they are automatically generated from other files. I have told the programmer that I know from personal experience that you can simply replace the & with & and the link will still work, but he tells me there are cases when that is not true. If so, then I wonder how anybody gets anything to validate?

To illustrate, he wrote this script which he named amp.php and uploaded to the server:

Here is a list of all variables received:<br>
	while (list($key, $val) = each($HTTP_GET_VARS)) {
		echo "|$key| is |$val|<br>";

The year is <?echo date("Y")?>

Then he wrote these two links to test it:;b=2&amp;c=3

The results are as follows:

first link:

Here is a list of all variables received:
|a| is |1|
|b| is |2|
|c| is |3|
The year is 2005

second link:

Here is a list of all variables received:
|a| is |1|
|amp;b| is |2|
|amp;c| is |3|
The year is 2005

Since the second scenario clearly shows that he can’t just replace ampersands to get the desired result, then web compliance is out the window. I find this very frustrating but I don’t understand PHP enough to make a clear argument for how to remedy this. He uses tons of links with &id_num in them, and NONE of them validate.

Any ideas? Thanks for your help.


you could use %26
that should work…

Thanks for the quick reply. I tried your suggestion by writing the link like this:

and this is the result:

Here is a list of all variables received:
|a| is |1&b=2&c=3|
The year is 2005

To achieve the same results as the first link the & sign would not be there. Plus the | disappears.

Any other suggestions? Thanks again, I really do appreciate it.

you could use the & and set $_GET = str_replace(“amp;”, “”, $_GET);

Thank you, php_Penguin, that worked!

Unfortunately that example was just the php coder trying to make a point. Here is a real-world example. The following link is in a PHP file. The link calls to each of a series of banner ads and makes the banner image link to the website while counting the clicks.

(php code goes here...)
(html code goes here...)

<a href="<?echo $bannerID?>&id_num=100000" target="link"><img src="<?echo $banner?>" alt="<?echo $alt?>" border="0"></a>

If I upload the above to the browser to see the web page, and mouseover the banner ad, this is what I see in the status bar:

On click, it goes to the website associated with the banner.

If I replace the & sign with & and upload the file to the browser, the URL looks identical to the above in the status bar on mouseover, but on click it doesn’t resolve to the correct website. Instead I get a page not found.

I hope that makes sense.


Actually the browser will automatically replace any &'s in the scource with & on the screen. This way when you click the link the url goes through as &'s and not &'s, the test you are using will not work because the url bar does not treat &'s the same as the browser itself.

Thanks Aaron. So to answer the main point… is there a way to write valid code in PHP… so that all links that have, for example, &id_num show as &id_num in the html code for validation purposes, but resolve correctly for practical purposes… is there a way to do that?


The browser will automatically change all &'s in the source to &'s for urls, textboxes etc. So just write the urls with &s and the browser will do the rest for you.

Hi Aaron, Actually I understand that… but for some reason &id_num makes the link “look” right but because the PHP is doing something else in the background (that I don’t understand) apparently it needs an actual ampersand. The link looks right and it validates, but it takes you to a “page not found” unless you use a plain ampersand.

I have done what you are suggesting many times in links but in this case it isn’t working and I don’t know why. The php programmer doesn’t think it can be done.


I went back to your original post and realized exactly what you were asking.
Okay here is what is happening, php parses the url and looks for three things and then on finding them breaks them into smaller chunks, first the ? after the script title which tells it there is a query. Secondly it looks for &'s which tell it there are variables. It then splits the different variables on the & kinda like you could with the explode function. It then parses each result for a variable name and value by looking on either side of the equal sign.
The reason that the &s don’t work when typed directly into the url bar is because php itself does not recognize & as a whole in a url as & sign therefore when it splits the variables apart it only looks at the & part of it and not the amp;. So basically when the url is put directly into the url bar or is never displayed to the browser (like a php redirect) the & stays as & and stops the url from working correctly.
However the programmer is just playing with you, what he said is like saying that the Sahara desert is not always hot and then turning on an air conditioner to prove his point. So just tell him to stop being a smart alek and do what he is told.
If he just replaces all the &'s in the source that actually appear in the browser it will work fine (&'s that do not show in the browser are not validated anyway so they don’t matter).

fyi, since this is about standards, the standards recomend using a ‘;’ instead of a ‘&’

Aaron.D has it right though, the & is for use in an html document, not as stand alone link.

Hi Aaron D. & jbw,

I couldn’t get the link to work if I wrote it & as I explained before. But changing the ampersand to a semicolon did the trick. So thanks to all of you for your help and Happy New Year!


PS - I found a good article on this. Hope it helps someone else.