I try to make my PHP cache with this code:
//Make cache files
$cache = 'tweets-cache.txt';
$date = 'tweets-date.txt';
$currentTime = time(); // Current time
// Get cache time
$datefile = fopen($date, 'r');
$cacheDate = fgets($datefile);
fclose($datefile);
//check if cache has expired
if (floor(abs(($currentTime-$cacheDate) / 10800)) <= $_GET['expiry'] && $cacheDate) {
$cachefile = fopen($cache, 'r');
$data = fgets($cachefile);
fclose($cachefile);
} else {
//Make the REST call
$data = (array) $cb->$api($params);
// update cache file
$cachefile = fopen($cache, 'wb');
fwrite($cachefile, utf8_encode($data));
fclose($cachefile);
// update date file
$datefile = fopen($date, 'wb');
fwrite($datefile, utf8_encode(time()));
fclose($datefile);
}
//Output result in JSON, getting it ready for jQuery to process
echo json_encode($data);
Now he writes nothing in tweets-cache.txt.
i think it is because of he cannot write an array with utf8_encode.
Yes, you are right about utf8_encode() function. Try to write serialized data to the file:
fwrite($cachefile, json_encode($data));
and when you read your data back from the file, do de-serialization:
$data = json_decode(fgets($cachefile));
Also, you can make things simpler if you use functions like file_get/put_contents, so your code:
$cachefile = fopen($cache, 'r');
$data = fgets($cachefile);
fclose($cachefile);
will be:
$data = json_decode(file_get_contents($cache));
and:
// update cache file
$cachefile = fopen($cache, 'wb');
fwrite($cachefile, utf8_encode($data));
fclose($cachefile);
// update date file
$datefile = fopen($date, 'wb');
fwrite($datefile, utf8_encode(time()));
fclose($datefile);
translates to:
// update cache file
file_put_contents($cache, json_encode($data));
// update date file
file_put_contents($date, time());
Be aware of the synchronization problems you can face when you are using filesystem in multithreaded/multiprocess environment.
Two and more php instances can make attempt to write data to the same file in the same time, and you will get corrupted file.
You can use filesystem locking or special cache software like Memcached, which is much more preferable solution for such cases.
Memcached
PHP Reference: file_put_contents()
PHP Reference: file_get_contents()
PHP Reference: json_encode()
Related
I am trying to get the API data from a cache file if there already was the same request recently. Everything works fine but I am just not able to get the content from the cache file even tho it is there. I can't find an error. I hope u can help me.
$url = /* API URL */;
function getJson($url) {
$cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url) . '.json';
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = filemtime($cacheFile);
if ($cacheTime > strtotime('-60 minutes')) {
$json = fread($fh);
return $json;
}
fclose($fh);
unlink($cacheFile);
}
$json = file_get_contents($url);
$fh = fopen($cacheFile, 'w');
fwrite($fh, $json);
fclose($fh);
return $json;
}
$datab = getJson($url);
$data = json_decode($datab, true);
print_r($data);
Il you dont check for your error log or display errors on screen you gonna have a bad time finding its.
Here you have a $cacheFile which should be a $cachePath, so prefix with './' or better DIR
Then you call fread without second parameter, and so on...check your error log, enable all errors.
You must specify the length that needs to be read in fread.
Use:
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = filemtime($cacheFile);
if ($cacheTime > strtotime('-60 minutes')) {
$json = fread($fh,filesize($cacheFile));
fclose($fh); //Remember to release resources
return $json;
}
fclose($fh);
unlink($cacheFile);
}
Alternatively use file_get_contents($cacheFile) to get the whole file without the need for an fopen first.
I am using weatherundeground.com to get weather data but I always reach the API calls limit so I was thinking about caching the json response every 60 minutes.
This is my simple php script
<?php
$json_string = file_get_contents("http://api.wunderground.com/api/apikey/conditions/forecast/lang:IT/q/CITY1.json");
$parsed_json = json_decode($json_string);
$city1 = $parsed_json->{'current_observation'}->{'display_location'}->{'city'};
I searched and found this answer: Caching JSON output in PHP
I tried to merge them like this:
$url = "http://api.wunderground.com/api/apikey/conditions/forecast/lang:IT/q/SW/Acquarossa.json";
function getJson($url) {
// cache files are created like cache/abcdef123456...
$cacheFile = 'cache' . DIRECTORY_SEPARATOR . md5($url) . '.json';
if (file_exists($cacheFile)) {
$fh = fopen($cacheFile, 'r');
$cacheTime = trim(fgets($fh));
// if data was cached recently, return cached data
if ($cacheTime > strtotime('-60 minutes')) {
return fread($fh);
}
// else delete cache file
fclose($fh);
unlink($cacheFile);
}
$json = file_get_contents($url);
$fh = fopen($cacheFile, 'w');
fwrite($fh, time() . "\n");
fwrite($fh, $json);
fclose($fh);
return $json;
}
$json_string = getJson($url);
$parsed_json = json_decode($json_string);
$city1 = $parsed_json->{'current_observation'}->{'display_location'}->{'city'};
I have been able to set it up and now it gets the first "round" of data, but the 2nd one and all the following, give me an error:
Warning: fread() expects exactly 2 parameters, 1 given in /home/*****/public_html/*****/acquarossa.php on line 27.
And if I put the cached json on any json validator, it says that it isn't a valid json.
( this is the cached file: http://spinnaker.url.ph/meteo/cache/1f58bbab7bf88f3f8561b769475cb7c1.json )
What can I do?
P.S.:I already CHMOD 777 the directory
Actually, the warning is pretty clear about whats going wrong. fread() expects 2 parameters but you're only passing on one in line 27: return fread($fh);
Reading the manual for fread I guess you can fix this by changing
return fread($fh);
to
return fread($fh, filesize($chacheFile));
$iplog = "$time EST - $userip - $location - $currentpage\n";
file_put_contents("iplog.txt", $iplog, FILE_APPEND);
I am trying to write this to the text file, but it puts it at the bottom and I would prefer if the new entries were at the top. How would I change the pointer for where it puts the text?
To prepend at the beginning of a file is very uncommon, as it requires all data of the file copied. If the file is large, this might get unacceptable for performance (especially when it is a log file, which is frequently written to). I would re-think If you really want that.
The simplest way to do this with PHP is something like this:
$iplog = "$time EST - $userip - $location - $currentpage\n";
file_put_contents("iplog.txt", $iplog . file_get_contents('iplog.txt'));
The file_get_contents solution doesn't have a flag for prepending content to a file and is not very efficient for big files, which log files usually are. The solution is to use fopen and fclose with a temporary buffer. Then you can have issues if different visitors are updating your log file at the same time, but's that another topic (you then need locking mechanisms or else).
<?php
function prepend($file, $data, $buffsize = 4096)
{
$handle = fopen($file, 'r+');
$total_len = filesize($file) + strlen($data);
$buffsize = max($buffsize, strlen($data));
// start by adding the new data to the file
$save= fread($handle, $buffsize);
rewind($handle);
fwrite($handle, $data, $buffsize);
// now add the rest of the file after the new data
$data = $save;
while (ftell($handle) < $total_len)
{
$chunk = fread($handle, $buffsize);
fwrite($handle, $data);
$data = $chunk;
}
}
prepend("iplog.txt", "$time EST - $userip - $location - $currentpage\n")
?>
That should do it (the code was tested). It requires an initial iplog.txt file though (or filesize throws an error.
I'm trying to set a persistent date stamp by writing it to a text file and then reading it back in each time the page is viewed.
// set the date, w/in if statements, but left out for brevity
$cldate = date("m/d/Y");
$data = ('clickdate' => '$cldate'); // trying to set a variable/value pair
- It's throwing an Error on this !
// Open an existing text file that only has the word "locked" in it.
$fd = fopen("path_to_file/linktrackerlock.txt", 'a') or die("Can't open lock file");
// Write (append) the pair to the text file
fwrite($fd, $data);
// further down …
// Open the text file again to read from it
$rawdata = fopen("path_to_file/linktrackerlock.txt", 'r');
// Read everything in from the file
$cldata = fread($rawdata, filesize("path_to_file/linktrackerlock.txt"));
fclose($rawdata);
// Echo out just the value of the data pair
echo "<div id='Since'>Clicks Since: " . $cldata['clickdate'] . "</div>";
$data = ('clickdate' => '$cldate');
needs to be:
$data = array('clickdate' => $cldate);
Additionally, you are required to pass a string to an fwrite statement, so there is no need to create an array:
$cldate = date("m/d/Y");
if($fd = fopen("path_to_file/linktrackerlock.txt", 'a')){
fwrite($fd, $cldate);
fclose($fd);
}else{
die("Can't open lock file");
}
Code's fundamentally broken. You're trying to create an array, then write that array out to a file:
$data = array('clickdate' => '$cldate');
^^^^^---missing
Then you have
fwrite($fd, $data);
But all that will do is write the word Array out to your file, NOT the contents of the array. You can try it yourself... just do echo $data and see what you get.
You could probably make this whole thing a lot simpler with:
$now = date("m/d/Y");
file_put_contents('yourfile.txt', $now);
$read_back = file_get_contents('yourfile.txt');
If you do insist on using an array, then you have to serialize or, or use another encoding format, like JSON:
$now = date("m/d/Y");
$arr = array('clickdate' => $now);
$encoded = serialize($arr);
file_put_contents('yourfile.txt', $encoded);
$readback = file_get_contents('yourfile.txt');
$new_arr = unserialize($readback_encoded);
$new_now = $new_arr['clickdate'];
I'm testing php because I'm a freshman in this matter. I put my php code in a free server, they let me do my own index.php, manage some php variables (like register_globals, magic_quotes_gpc etc. I left them as default), but apparently I can handle not more than one file in a php code, for example:
<?php
//--------Updating Data-------------
$cdc = intval($_POST['cantidadDeCapitulos']);
$toWrite = array('ctot' => $cdc);
for($i=1;$i<$cdc+1;$i += 1){
$toWrite["cap".$i] = $_POST['numdeCap'.$i];
}//---------------------------------
$datos = file_get_contents("myfile.json.");
$toWrite = json_encode( $toWrite );
//Open a file in write mode
$fp = fopen("myfile2.json", "w");
if(fwrite($fp, "$toWrite")) {
echo "&verify=success&";
} else {
echo "&verify=fail&";
}
fclose($fp);
?>
If I comment out the line $datos = file_get_contents("myfile.json."); it's alright!, something is written in myfile2.json but if it is uncommented, the data is not updated. Both files have permission 666 and they are in the same directory i.e., /root.
$datos = file_get_contents("myfile.json.");
Seems like a typo has occurred. Take off the final dot from your file. I mean, change the line to:
$datos = file_get_contents("myfile.json");
try this:
<?php
$file = 'myfile.json';
// Open the file to get existing content
$current = file_get_contents($file);
// Write the contents back to the file
file_put_contents($file, $current);
?>