I want to cache the API responses so that number of requests to the API server are reduced. API's are written in PHP using zend framework.
My approach: I created a redis cluster and I used phpfastcache to connect to redis cluster. Using phpfastcache, we can only set the expiry time for the cached response.
Whenever the response is updated before expiry of cache, we get the older response with the approach mentioned above. Desired thing is that whenever response is updated, old cache must be cleared and new cache must be written with same key.
I have attached a sample script that I used.
It would be great if anyone can provide me solution for this.
Thanks in advance.
Code:
<?php
// phpfastcache is a package used for caching
use Phpfastcache\CacheManager;
use Phpfastcache\Drivers\Redis\Config;
require //path for composer autoloader;
#InstanceCache must be global
$InstanceCache = CacheManager::getInstance('redis', new Config([
'host' => 'IP_address',
'port' => 6379,
'password' => //password
'database' => //db_name
]));
public function function_name(parameter){
$key = "unique_name";
$CacheString = $InstanceCache->getItem($key);
if(is_null($CacheString->get())){
$sql="SELECT * FROM employees";//sql query for function_name
$res=$this->db_query($sql);
if($this->db_num_rows($res)==0):
$this->db_free_results($res);
else:
$row = $this->db_fetch_object($res);
$this->db_free_results($res);
endif;
$CacheString->set($row)->expiresAfter(/*time*/);
$InstanceCache->save($CacheString);
echo $CacheString->get();
}
else{
echo $CacheString->get();
}
}
?>
Like I told you on Github, I think you misunderstood the concept itself of caching.
The concept caching means that you cache your data for a desired TTL.
If you need the most fresh data then you must re-fetch from source (your database here ).
Cache is not means to be dynamic, it's means to be static and to help you cool down the request on your backend.
So in your case, just fetch from source without caching and it'll be good. It does not make any sense to ask Phpfastcache interrogate your database each time then compare the data to the cached data to check if your database data are fresher.
In fact the cost in time of the whole operation will be longer than only fetching from the source.
Related
I am looking for a solution in CakePhp, to store and read temporary datas :
I read some XML from others websites in order to display some news in my website, but on each page load, it does a call to the other xml websites.
Is there a way (memcached like) to save temp. data in CakePhp in order to store data for 1 hour and read temp. data to display them in my webpages ; then 1 hour after update them (with cron) ?
Thanks.
CakePHP Caching seems what you'd want.
WHICH cache you use (Redis, Memcache...etc) would be up to you though. Set your cache to last an hour, and you're all set. (read more about cache on the link above).
If you're on CakePHP 2.5+, you can use the remember method described here.
public function newest() {
$model = $this;
return Cache::remember('newest_posts', function() use ($model){
// get your data from whatever source here, and return it
return $model->getMyData();
}, 'long');
}
Basically, this just checks to see if the cache key exists, and if not, runs some code in order to populate it again.
If you're below 2.5, you can do the same basic thing, but without the remember:
public function newest() {
$result = Cache::read('newest_posts', 'long');
if (!$result) {
// get your data from whatever source here, and write it
Cache::write('newest_posts', $this->getMyData(), 'long');
}
return $result;
}
If you don't have a cache engine installed or are aren't wanting to mess w/ your own server, there are companies that you can use for cache, and you can just set your cache settings to connect to them. ObjectRocket (Redis) is the one I know offhand, but I'm sure there are plenty.
One of many awesome things about CakePHP, is that in this case, your code doesn't change regardless of Cache type/location/configuration you choose.
I'm using Live Reporting Google APIs to retrieve active users and display the data inside a mobile application. On my application I'd like to make a HTTP request to a PHP script on my server which is supposed to return the result.
However I read on Google docs that it's better not to request data using APIs more often than 30 seconds.
I prefer not to use a heavy way such as a cron job that stores the value inside my database. So I'd like to know if there's a way to cache the content of my PHP scrpit na dmake it perform an API request only when the cache expires.
Is there any similar method to do that?
Another way could be implementing a very simple cache by yourself.
$googleApiRequestUrlWithParameter; //This is the full url of you request
$googleApiResponse = NULL; //This is the response by the API
//checking if the response is present in our cache
$cacheResponse = $datacache[$googleApiRequestUrlWithParameter];
if(isset($cacheResponse)) {
//check $cacheResponse[0] for find out the age of the cached data (30s or whatever you like
if(mktime() - $cacheResponse[0] < 30) {
//if the timing is good
$googleApiResponse = $cacheResponse[1];
} else {
//otherwise remove it from your "cache"
unset($datacache[$googleApiRequestUrlWithParameter]);
}
}
//if you do no have the response
if(!isset($googleApiResponse)) {
//make the call to google api and put the response in $googleApiResponse then
$datacache[] = array($googleApiRequestUrlWithParameter => array(mktime(), $googleApiResponse)
}
If you data are related to the user session, you could store $datacahe into $_SESSION
http://www.php.net/manual/it/reserved.variables.session.php
ortherwise define $datacache = array(); as a global variable.
There is a lot of way of caching things in PHP, the simple/historic way to manage cache in PHP is with APC http://www.php.net/manual/book.apc.php
Maybe I do not understard correctly your question.
How can i cache a particular part of the web page, I know how CI caching mechanism works also i am aware of Partial Caching.
Assume that we have a page with some dynamic data associated with. If i used caching then i cannot get the actual data on page refresh.
How can i override this problem ?
I have one idea in my mind, While inserting the data just keep another field, lets say MD5_CONTENTS which will store the MD5 hash of the contents ( Normally form fields ). And next time on update i can compare the MD5 strings to determine changes. If changes are found then delete the cache file.
I dont know this is gonna work or not, But its littlebit hard for my current implementation.
What is the best method to achieve Partial Caching ?
Thanks
Would the caching driver do the trick?
http://ellislab.com/codeigniter/user-guide/libraries/caching.html
$this->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file'));
if ( ! $foo = $this->cache->get('foo'))
{
echo 'Saving to the cache!<br />';
$foo = 'foobarbaz!';
// Save into the cache for 5 minutes
$this->cache->save('foo', $foo, 300);
}
echo $foo;
Ok here is the link to the cache library he wrote: https://github.com/philsturgeon/codeigniter-cache
Anyway, his documentation is absolutely.. vague and not helpful at all. I know it's self explanatory.. to a point.
$this->cache->model('blog_m', 'getPosts', array($category_id, 'live'), 120); // keep for 2 minutes
What is the 3rd parameter?
And is that what creates the cache or this what creates a cache file:
$this->cache->write($data, 'cached-name');
And if that is, what exactly is $data suppose to be holding a value of? The overall query orrr...??
If anyone could give explanation on this on how you create a cache file.. Basically I want to cache the query that selects a bunch of news postings.. and everytime a new new post is created, to delete that cache and recache it so it shows the new news posting..
The documentation seems to be fairly clear. Anyways, I'll try to explain it in better terms:
// cached model call
$this->cache->model('blog_m', 'getPosts', array($category_id, 'live'), 120); // keep for 2 minutes
This calls the method getPosts on the model blog_m and caches the result for 120 seconds. If you make the same call again within the next 2min, it will return the cached results, otherwise it will fetch the data from the database and update the cache. It's good for methods on models that you will be calling very frequently.
If you want to manually add and get data from a cache, then you use:
// cached array or object
$this->cache->write($data, 'cached-name');
$data = $this->cache->get('cached-name');
$data will hold whatever you want to cache. If you want to cache the user's email, for example, here's how you would cache and fetch it
$email = 'foobar#example.com';
$this->cache->write($email, 'user-email');
// to fetch
$user_email = $this->cache->get('user-email');
I feel a bit anxious to put my database username, password and encryption keys into a PHP file that everyone who hacked himself into the server could easily read. Is it maybe possible to load PHP and tell it the passwords it might need upfront?
My question is simple: Is there any other way to let PHP know about the DB password and key other than to put everything into one file?
Any ideas are welcome.
To my knowledge you will have to declare your variables at some point in order to initiate a DB connection. You can, however, do certain things to make it more difficult for someone to read it.
In addition to safe programming practices mentioned in another answer, you can be sure to only store your passwords in one file (such as Config.php) and include it in your database connection function. Moreover, you can store this variable outside the web root, meaning that people will not be able to access it unless they have server access.
You can also make it more difficult to be read for someone who gains access. This includes encrypting it with a Symmetric Key Algorithm, and then decrypting it when used. Note that the encryption/decryption key will have to also be stored on the server which, again, make this little more than an inconvenience.
Take proper security steps in securing your code, and restrict your database so it can only be accessed locally. This should provide ample security.
Technically speaking, nobody cant see your php scripts. Anyways, I just updated my DB macros to the newest standards. This is how I do things in my CMS:
config.php file:
<?
if (!defined('A52CMS')) {die('What are you looking for? 0.o');}
$config_mysql = array(
'database' => 'databasename1',
'user' => 'username1',
'password' => 'password1',
'table_prefix' => 'a52_'
);
db_macros.php file:
<?
if (!defined('A52CMS')) {die('What are you looking for? 0.o');}
class DB {
protected $default_config = array(
'server' => 'localhost',
'database' => '',
'user' => 'root',
'password' => '',
'table_prefix' => 'a52_',
'mysql_config_array' => 'config_mysql'
);
function __construct ($config_mysql) {
$this->config = array_merge($this->default_config, $config_mysql);
/* There are some secret connection related stuff here */
mysql_query("SET NAMES utf8");
unset($this->config['password']);
unset($GLOBALS[$this->config['mysql_config_array']]);
}
/* There are alot of mysql related functions here */
function __destruct () {
mysql_close($this->conn);
if (#mysql_ping($this->conn)) {
CriticalError('Closing mysql connection was unsuccessful!');
}
}
}
core.php file:
<?
if (!defined('A52CMS')) {die('What are you looking for? 0.o');}
require('config.php');
// Lets try to display the mysql raw data
print_r($config_mysql); // displays something
require('db_macros.php');
$DB = new DB($config_mysql);
// Lets try to display the mysql raw data AGAIN
print_r($config_mysql); // displays nothing
index.php file:
<?
define('A52CMS', true);
require('core.php');
// This where the content starts.. if some plugin is being included, then mysql data is already unset, so basically you cannot hack them..
You might get some ideas how to make your applications little bit more secure. Also you might get some new ideas on how to contruct your custom mysql class (if you havent done so already.)
make secure scripts. If your scripts are secure, there's no way to get hacked
make your scripts which contains password(s) only apache-readable
make sure access to your password files are out of web scope
I did not even see another method to "save" password(s) than these