Beware: this post is definitely not for the feint of heart. It includes a lot of code. You have been warned.
I wrote an application some time ago for my company that looks up the longitude and latitude of an address for use in our geocoding initiative. It relied on yahoo_geo(), a function written by PHP creator Rasmus Lerdorf and the Yahoo Maps API. It was largely dependent on this function:
function yahoo_geo($location) { $q = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=rlerdorf&location=' .rawurlencode($location); $tmp = '/tmp/yws_geo_'.md5($q); request_cache($q, $tmp, 43200); libxml_use_internal_errors(true); $xml = simplexml_load_file($tmp); $ret['precision'] = (string)$xml->Result['precision']; foreach($xml->Result->children() as $key=>$val) { if(strlen($val)) $ret[(string)$key] = (string)$val; } return $ret; } |
This function worked for over two years for us with no problems at all. Then suddenly, in the last month, it started getting spotty. I fixed things by commenting out the caching parts of the function and forcing each execution to run again. Then I got errors about the libxml_use_internal_errors() function, so I commented that out. But today, the function just flat out failed, every single time returning the same error:
Warning: file_get_contents(http://XXXXXXXXXX/XXX) [function.file-get-contents]: failed to open stream: HTTP request failed! in /home/intranet/html/fetch.php on line X
What the heck? This code is all over the web. I’ve tried a million permutations of this function, including using fopen() and ob_get_contents(), and none have worked. And most frustratingly, I could load the URL successfully in Lynx and eLinks, so the machine could quickly and easily fetch the URL.
So I ventured into a sandbox I’ve never really played before: cURL. cURL is an interesting animal. But the interesting thing is, once I got it working, it worked faster than ever! So, without further ado, here is the new and improved yahoo_geo() function:
function yahoo_geo($location) { $q = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=rlerdorf&location='.urlencode(trim($location)); $ch = curl_init($q); curl_setopt($ch, CURLOPT_HEADER, 0); ob_start(); curl_exec($ch); $stream = ob_get_contents(); ob_end_clean(); if($stream) { $xml = simplexml_load_string($stream); $ret['precision'] = (string)$xml->Result['precision']; if($xml) { foreach($xml->Result->children() as $key=>$val) { if(strlen($val)) $ret[(string)$key] = (string)$val; } } curl_close($ch); return $ret; } else { return FALSE; } } |
Note: If you’re reproducing these functions elsewhere, be careful – WordPress may have converted the quotes into smart quotes that will need to be fixed before this script will run properly.
You may have allow_url_fopen disabled in your php.ini or a .htaccess file. use phpinfo() to see the configuration value
Good thought, but that was the first thing I verified. allow_url_fopen is and always has been on, which is why it worked in the first place.
You don't need the ob_start in the curl example.
You can use:
function read_whatever ($ch, $str) {
}
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'read_body');
(it was copied from a multi-curl-example, but it should work)
Lennie
You don't need the ob_start in the curl example.
You can use:
function read_whatever ($ch, $str) {
}
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'read_body');
(it was copied from a multi-curl-example, but it should work)
Lennie