Texan78 Posted December 20, 2014 Share Posted December 20, 2014 (edited) Hello, I am needing to cache a json response from an API so I am not making requests on each load. I have come across some code that is suppose to accomplish this but, it seems to not be working and can't figure out as to why. I created the cache file with 777 but it doesn't write or read from that file when I echo out the results. The code below is just what is suppose to get the contents and cache it. At the end I tried to print it so I can test it to see it prints the response from the cache file but, nothing and the cache file does exists. This is the first time I have tried something like this so please be gentle. // cachePath is name of the path and file used to store cached current conditions gathered from the API request $cachePath = "./cache/nowcast-cache.txt"; // URL to the API request $url = "http://api.wunderground.com/api/XXXXXXXXXXXX/geolookup/conditions/q/TX/mesquite.json"; date_default_timezone_set('America/Chicago'); /** * Request jobs from API * * Split the request into smaller request chunks * and then consolidate them into a single array to limit the API * requests. */ function api_request() { file_put_contents($cachePath, file_get_contents($url)); } /** * API Request Caching * * Use server-side caching to store API request's as JSON at a set * interval, rather than each pageload. * * @arg Argument description and usage info */ function json_cached_api_results( $cache_file = NULL, $expires = NULL ) { global $request_type, $purge_cache, $limit_reached, $request_limit; if( !$cache_file ) $cache_file = dirname(__FILE__) . $cachePath; if( !$expires) $expires = time() - 2*60*60; if( !file_exists($cache_file) ) die("Cache file is missing: $cache_file"); // Check that the file is older than the expire time and that it's not empty if ( filectime($cache_file) < $expires || file_get_contents($cache_file) == '' || $purge_cache && intval($_SESSION['views']) <= $request_limit ) { // File is too old, refresh cache $api_results = api_request(); $json_results = json_encode($api_results); // Remove cache file on error to avoid writing wrong xml if ( $api_results && $json_results ) file_put_contents($cache_file, $json_results); else unlink($cache_file); } else { // Check for the number of purge cache requests to avoid abuse if( intval($_SESSION['views']) >= $request_limit ) $limit_reached = " <span class='error'>Request limit reached ($request_limit). Please try purging the cache later.</span>"; // Fetch cache $json_results = file_get_contents($cache_file); $request_type = 'JSON'; } return json_decode($json_results); } print_r($json_results); Edited December 20, 2014 by Texan78 Quote Link to comment Share on other sites More sharing options...
QuickOldCar Posted December 21, 2014 Share Posted December 21, 2014 I'll tell you how I cache my api json responses locally I store my cache in /var/cache/api/ permissions set to 755 and owner www-data Not sure how you have your api set up, but my scripts are includes through the server if passes api checks I believe you are trying to cache external api requests? Well this can cache anything, make a script that fetches and displays the data, call on that script, the cache will do the rest. You can change the folder location to where you need it. api-cache.php <?php class cache { var $cache_dir = '/var/cache/api/'; //cache storage location var $cache_time = 86400; //cache storage time in seconds var $caching = false; var $file = ''; function cache() { $this->file = $this->cache_dir . urlencode( $_SERVER['REQUEST_URI'] ); if ( file_exists ( $this->file ) && ( fileatime ( $this->file ) + $this->cache_time ) > time() ) { //read cache $handle = fopen( $this->file , "r"); do { $data = fread($handle, 8192); if (strlen($data) == 0) { break; } echo $data; } while (true); fclose($handle); exit(); } else { //create cache $this->caching = true; ob_start(); } } //close cache function close() { if ( $this->caching ) { $data = ob_get_clean(); echo $data; $fp = fopen( $this->file , 'w' ); fwrite ( $fp , $data ); fclose ( $fp ); } } } ?> Usage require_once('api-cache.php'); $ch = new cache(); echo date("D M j G:i:s T Y"); //cached content area $ch->close(); Quote Link to comment Share on other sites More sharing options...
Texan78 Posted December 21, 2014 Author Share Posted December 21, 2014 Thanks for the suggestion. I been trying it out. I do already have the script that will read from a cache file and it works great. This issue is trying to cache the API response from a URL. A couple of questions. Should the below set to true and would the $file be the URL to the API response I want to cache? var $caching = false; var $file = ''; Quote Link to comment Share on other sites More sharing options...
QuickOldCar Posted December 21, 2014 Share Posted December 21, 2014 Those are just default defines, no need to edit those. The cache is saving your scripts by address bar names. Make a script with dynamic values from your address bar, the script connects to the api with the dynamic values. Your script connects to external api, returns json data on the page. You now would want to connect to your script as if it was the api. Quote Link to comment Share on other sites More sharing options...
hansford Posted December 22, 2014 Share Posted December 22, 2014 You are using a relative url for the path. I don't where the file is relative to your script, but I would use __DIR__ or $_SERVER['DOCUMENT_ROOT'] Before I write external functions, class files, etc. I throw together a basic bare bones script and execute it. I do this just so I know I have the path correct, that I can use file_get_contents(), that my file permissions are correct etc. error_reporting(E_ALL); ini_set('display_errors',1); define('br', '<br />'); $cachePath = $_SERVER['DOCUMENT_ROOT'] . '/cache/nowcast-cache.txt'; $url = 'http://api.wunderground.com/api/XXXXXXXXXXXX/geolookup/conditions/q/TX/mesquite.json'; if(($data = @file_get_contents($url)) === false) { echo 'file_get_contents() failed as usual' . br; exit(); // no need to go any further until this is fixed } if((@file_put_contents($cachePath, $data)) === false) { echo 'file_put_contents() failed' . br; } Quote Link to comment Share on other sites More sharing options...
Texan78 Posted December 30, 2014 Author Share Posted December 30, 2014 I seem to have this working fairly well now. It writes and reads from it. How would I add to it so it only checks the URL X amount of times I.E. every hour? $cache = $_SERVER['DOCUMENT_ROOT'] . $cachePath; $url = 'http://api.aerisapi.com/observations/KHQZ?client_id='. $ID .'&client_secret='. $client_secret.''; if(($data = @file_get_contents($url)) === false) { echo 'file_get_contents() failed as usual' . br; exit(); // no need to go any further until this is fixed } if((@file_put_contents($cachePath, $data)) === false) { echo 'file_put_contents() failed' . br; } -Thanks Quote Link to comment Share on other sites More sharing options...
hansford Posted December 30, 2014 Share Posted December 30, 2014 You are going to have to create a cron job for that - a scheduled task on the server. I don't have time to go over it right now, but maybe others will chime in - or you can look up how to do that. You will need to modify your script - possibly have to add a bash command up top. You can set it up to email you when the task is complete. Quote Link to comment Share on other sites More sharing options...
Texan78 Posted January 1, 2015 Author Share Posted January 1, 2015 Currently I use a cron to write to a file then the script reads from that file. I am trying to do it without having to use a cron. That is what I was trying to accomplish with the code in my original post. Otherwise it is redundant with the suggested code since wget in a cron does the same thing. Quote Link to comment Share on other sites More sharing options...
hansford Posted January 1, 2015 Share Posted January 1, 2015 I would reword the problem - exactly - and repost - let other's have a nibble at it. Quote Link to comment Share on other sites More sharing options...
Texan78 Posted January 2, 2015 Author Share Posted January 2, 2015 I am really not sure what more I could add that isn't already explained and added with the code in the orignal post. The code posted should do what I need it to do but, it doesn't write or read to the cache. That was the reason for this post. When the page is called the script will write to a cache file the response from the API. If the response is under X age then don't call the API. If it is over X age then request a new response and cache it. The script will read from the cache the response. The part of the script that reads from the cache works great. I am just having problems with writing to cache and having the code read from the cache file. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.