Sometimes you see this great tile layer in a web map and you want to use it in your ArcGIS online project or ArcGIS Pro. That was the feeling I had, seeing this nice little BVG basemap. The usage of this kind-of-twisted basemap was a bit tricky as the logic for latitude-longitude to tile numbers was a bit twisted. In products like ArcGIS Online/ ArcGIS Enterprise there is no way to alter the logic of this. So if you want to use a tile layer like this in AGOL you need to intervene somewhere else.
Interrupt the Tile Acquisition
The tiles are fetched from a server any time you pan or zoom the map. The approach I used to get the tiles uses a simple php proxy.
So instead of collecting the tiles from the webserver via a direct pull, we use the php script which gets our request, calculates the somewhat twisted tile number for the row and requests the correct tile and forwards it to your AGOL project.
But let us start with a simple trick which serves as the basis: kitten watermarks.
PlaceKitten serves placeholder images in a very common format: http://placekitten.com/256/256?image=5 where the first "256" is the width, the second one the height and the last one the image you would like to see (image number 5). The images are served as PNGs.
As said, we will use a php script to fetch the data and send every image back to AGOL as we receive it. This makes no sense at all from a geo perspective. So you will need a php-enabled server. I was using a Windows virtual machine with IIS and installed PHP by using the Web Platform Installer.
So we need a way to fetch images from the web using php. I stumbled upon the cURL method you might already know from the command line world of Linux based systems.
All we need to do is to mimic our script to look like a real computer trying to get an image from this server:
<SPAN class="php token"><SPAN class="delimiter token"><?php</SPAN>
header <SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Content-Type: image/png'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#content returns as an image</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//placekitten.com/256/256?image='; #this is the base url</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">rand</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">16</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#we can collect one out of 16 images</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="variable token">$ynew</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#Initialize a cURL session</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#don</SPAN><SPAN class="string token">'t verify the peer'</SPAN>s <SPAN class="token constant">SSL</SPAN> certificate
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#don't use any cache</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#provide the URL to use in the request</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#return the transfer as a string of the return value of curl_exec() instead of outputting it directly. </SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#set HTTP user-agent header </SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#perform the cURL session</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#Close the cURL session</SPAN>
<SPAN class="keyword token">echo</SPAN> <SPAN class="variable token">$data</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#return the date (image)</SPAN>
<SPAN class="delimiter token">?></SPAN></SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
Now you can already use the real URL of your server (don't even try localhost my friend 😉 ) and embed the placeholder cats in your AGOL project.
Open up a new web map and add a new web based layer:
I am using here the proposed "{level}/{col}/{row}.png" connotation as we would like to create new calls for every image to get a true random pattern:
Look, all those cute kitties...
Running real Cartography
At the very moment we do have an idea on how to forward images from the web into AGOL as a web layer. Now let's move on and fill these placeholder with "real cartography".
As we have seen in this last post, the naming schema for the BVG map is a bit crooked. But first, our script needs to know, which images it should pull. So we need to send the script some parameters. We will do this in a similar way like the real TMS servers: Send the ZXY parameters via the URL, read the in our script and append the URL with them:
<SPAN class="php token"><SPAN class="delimiter token"><?php</SPAN>
header <SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Content-Type: image/png'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$y</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'y'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#the parameter y is stored as a string in the variable y</SPAN>
<SPAN class="variable token">$x</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'x'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#the parameter x is stor...</SPAN>
<SPAN class="variable token">$z</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'z'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#you get it, right?</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN><SPAN class="punctuation token">(</SPAN> <SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="operator token">*</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$y</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">+</SPAN><SPAN class="token function">pow</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$z</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#recalculate the y coordinate using the found formula.</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//fahrinfo.bvg.de/tiles/base/'.$z.'/'.$x.'/'.$ynew.'.png'; #creating the url</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">echo</SPAN> <SPAN class="variable token">$data</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="delimiter token">?></SPAN></SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
The parameters are send to the PHP-enabled server using the following schema:
http://your-server-URL.com/name-of-your-script.php?z={level}&x={col}&y={row}
Using this script you will get a nice BVG basemap in your ArcGIS Online editor Map Viewer:

Once you saved the web map you can even open it in ArcGIS Pro and use it for your purposes by adding the map from Portal:

Multiple Servers
If you want to handle multiple servers with the same script you can add a fourth parameter which handles the tileserver and adding some switches:
<SPAN class="php token"><SPAN class="delimiter token"><?php</SPAN>
header <SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Content-Type: image/png'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$tileservice</SPAN><SPAN class="operator token">=</SPAN><SPAN class="keyword token">null</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#</SPAN>
<SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="token function">isset</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'t'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="variable token">$tileservice</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'t'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="keyword token">if</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="operator token">!</SPAN><SPAN class="variable token">$tileservice</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="variable token">$tileservice</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="string token">'bvg'</SPAN><SPAN class="punctuation token">;</SPAN> <SPAN class="shell-comment comment token">#if no tileserver parameter was handled</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="variable token">$y</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'y'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$x</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'x'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$z</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'z'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">array</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">switch</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$tileservice</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="keyword token">case</SPAN> <SPAN class="string token">'cat'</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//placekitten.com/256/256?image=';</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">rand</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">16</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="variable token">$ynew</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="shell-comment comment token">#echo $url;</SPAN>
<SPAN class="keyword token">break</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">case</SPAN> <SPAN class="string token">'bvg'</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">default</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN><SPAN class="punctuation token">(</SPAN> <SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="operator token">*</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$y</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">+</SPAN><SPAN class="token function">pow</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$z</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//fahrinfo.bvg.de/tiles/base/'.$z.'/'.$x.'/'.$ynew.'.png';</SPAN>
<SPAN class="keyword token">break</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">echo</SPAN> <SPAN class="variable token">$data</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="delimiter token">?></SPAN></SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>Now your proxy URL should look like this to get a cat tile:
http://your-server-URL.com/name-of-your-script.php??t=cat&z=15&x=16371&y=10936
Sometimes you also want to have a fallback server if no tiles were fetched. Therefore we will check response of the cURL call and will use a black-white layer as a fallback layer:
<SPAN class="php token"><SPAN class="delimiter token"><?php</SPAN>
header <SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Content-Type: image/png'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">error_reporting</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="token constant">E_ALL</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">ini_set</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">'display_errors'</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">'1'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$tileservice</SPAN><SPAN class="operator token">=</SPAN><SPAN class="keyword token">null</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="token function">isset</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'t'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="variable token">$tileservice</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'t'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="keyword token">if</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="operator token">!</SPAN><SPAN class="variable token">$tileservice</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="variable token">$tileservice</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="string token">'bvg'</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="variable token">$y</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'y'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$x</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'x'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$z</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'z'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">array</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">switch</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$tileservice</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="keyword token">case</SPAN> <SPAN class="string token">'cat'</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="shell-comment comment token">#$server[] = 'https:</SPAN><SPAN class="comment token">//placekitten.com/256/256';</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//placekitten.com/256/256?image=';</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">rand</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">16</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="variable token">$ynew</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="shell-comment comment token">#echo $url;</SPAN>
<SPAN class="keyword token">break</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">case</SPAN> <SPAN class="string token">'bvg'</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">default</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN><SPAN class="punctuation token">(</SPAN> <SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="operator token">*</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$y</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">+</SPAN><SPAN class="token function">pow</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$z</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//fahrinfo.bvg.de/tiles/base/'.$z.'/'.$x.'/'.$ynew.'.png';</SPAN>
<SPAN class="keyword token">break</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="token function">curl_getinfo</SPAN><SPAN class="punctuation token">(</SPAN> <SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLINFO_HTTP_CODE</SPAN> <SPAN class="punctuation token">)</SPAN> <SPAN class="operator token">!=</SPAN> <SPAN class="number token">200</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">array</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> 'http<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//a.tiles.wmflabs.org/bw-mapnik/';</SPAN>
<SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> 'http<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//b.tiles.wmflabs.org/bw-mapnik/';</SPAN>
<SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> 'http<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//c.tiles.wmflabs.org/bw-mapnik/';</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="token function">array_rand</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="variable token">$z</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="string token">"/"</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="variable token">$x</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="string token">"/"</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="variable token">$y</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="string token">".png"</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="shell-comment comment token">#echo $url;</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">echo</SPAN> <SPAN class="variable token">$data</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="delimiter token">?></SPAN></SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>The map shows now both tiles:

If you want to add some "annoying annotation" you might also add a nice watermark on those slippy tiles:
<SPAN class="php token"><SPAN class="delimiter token"><?php</SPAN>
header <SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Content-Type: image/png'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">error_reporting</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="token constant">E_ALL</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">ini_set</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">'display_errors'</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">'1'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$tileservice</SPAN><SPAN class="operator token">=</SPAN><SPAN class="keyword token">null</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="token function">isset</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'t'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="variable token">$tileservice</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'t'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="keyword token">if</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="operator token">!</SPAN><SPAN class="variable token">$tileservice</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="variable token">$tileservice</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="string token">'bvg'</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="variable token">$y</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'y'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$x</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'x'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$z</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$_GET</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'z'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">array</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">switch</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$tileservice</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">{</SPAN>
<SPAN class="keyword token">case</SPAN> <SPAN class="string token">'cat'</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="shell-comment comment token">#$server[] = 'https:</SPAN><SPAN class="comment token">//placekitten.com/256/256';</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//placekitten.com/256/256?image=';</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">rand</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">16</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="variable token">$ynew</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="shell-comment comment token">#echo $url;</SPAN>
<SPAN class="keyword token">break</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">case</SPAN> <SPAN class="string token">'bvg'</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">default</SPAN><SPAN class="punctuation token">:</SPAN>
<SPAN class="variable token">$ynew</SPAN> <SPAN class="operator token">=</SPAN><SPAN class="punctuation token">(</SPAN> <SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="operator token">*</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$y</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">+</SPAN><SPAN class="token function">pow</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token function">intval</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$z</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="operator token">-</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> 'https<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//fahrinfo.bvg.de/tiles/base/'.$z.'/'.$x.'/'.$ynew.'.png';</SPAN>
<SPAN class="keyword token">break</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$size</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_getinfo</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLINFO_SIZE_DOWNLOAD</SPAN> <SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="token function">curl_getinfo</SPAN><SPAN class="punctuation token">(</SPAN> <SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLINFO_HTTP_CODE</SPAN> <SPAN class="punctuation token">)</SPAN> <SPAN class="operator token">!=</SPAN> <SPAN class="number token">200</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="punctuation token">{</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="keyword token">array</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> 'http<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//a.tiles.wmflabs.org/bw-mapnik/';</SPAN>
<SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> 'http<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//b.tiles.wmflabs.org/bw-mapnik/';</SPAN>
<SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> 'http<SPAN class="punctuation token">:</SPAN><SPAN class="comment token">//c.tiles.wmflabs.org/bw-mapnik/';</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="token function">array_rand</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$server</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$url</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="operator token">=</SPAN> <SPAN class="variable token">$z</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="string token">"/"</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="variable token">$x</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="string token">"/"</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="variable token">$y</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="string token">".png"</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="shell-comment comment token">#echo $url;</SPAN>
<SPAN class="variable token">$ch</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_init</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_SSL_VERIFYPEER</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token boolean">false</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_FRESH_CONNECT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">TRUE</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_URL</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$url</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="token constant">CURLOPT_RETURNTRANSFER</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">curl_setopt</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token constant">CURLOPT_USERAGENT</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$data</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">curl_exec</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="punctuation token">}</SPAN>
<SPAN class="token function">curl_close</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$ch</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$im</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">imagecreatefromstring</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$data</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$stamp</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">imagecreatetruecolor</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="number token">100</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">30</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">imagestring</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$stamp</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">10</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">10</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">5</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">'watermark'</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">0xff0000</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="comment token">// set borders and get sizes</SPAN>
<SPAN class="variable token">$marge_right</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="number token">100</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$marge_bottom</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="number token">100</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$sx</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">imagesx</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$stamp</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="variable token">$sy</SPAN> <SPAN class="operator token">=</SPAN> <SPAN class="token function">imagesy</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$stamp</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="comment token">// copy the watermark with transparency of 50 into the original image</SPAN>
<SPAN class="token function">imagecopymerge</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$im</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="variable token">$stamp</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token function">imagesx</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$im</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="operator token">-</SPAN> <SPAN class="variable token">$sx</SPAN> <SPAN class="operator token">-</SPAN> <SPAN class="variable token">$marge_right</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token function">imagesy</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$im</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="operator token">-</SPAN> <SPAN class="variable token">$sy</SPAN> <SPAN class="operator token">-</SPAN> <SPAN class="variable token">$marge_bottom</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">0</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">0</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token function">imagesx</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$stamp</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="token function">imagesy</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$stamp</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="number token">50</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">header</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Content-Type: image/png'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">imagepng</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$im</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="token function">imagedestroy</SPAN><SPAN class="punctuation token">(</SPAN><SPAN class="variable token">$im</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">;</SPAN>
<SPAN class="delimiter token">?></SPAN></SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>But this will create some load on the server... so you might want to rethink this 😉

Final remarks
Running PHP with a "bad" script can produce a very slow response of your proxied tile server. So you should try to cache tiles on your server. But this is a total different story.