I'm developing on GAE using Resin, it seems that my PHP session on the production site is short lived and doesn't get updated (i.e., making requests doesn't seem to increase it's expiry period). Local is fine, as long as I don't close the tab, the session persists.
Any pointer on this? My users are getting frustrated as they are kicked very frequently :(
I think the code is the best tutorial :)
// global mem cache service handle
$MEM_CACHE_SERVICE = NULL;
// table to store session like information
$MY_SESSION_TABLE = array();
function load_mcache($key) {
global $MEM_CACHE_SERVICE;
if (!$MEM_CACHE_SERVICE) {
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.memcache.Expiration;
$MEM_CACHE_SERVICE = MemcacheServiceFactory::getMemcacheService();
}
return $MEM_CACHE_SERVICE->get($key);
}
function save_mcache($key, $value, $cache_time) {
global $MEM_CACHE_SERVICE;
if (!$MEM_CACHE_SERVICE) {
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.memcache.Expiration;
$MEM_CACHE_SERVICE = MemcacheServiceFactory::getMemcacheService();
}
$expiration = Expiration::byDeltaSeconds($cache_time);
return $MEM_CACHE_SERVICE->put($key, $value, $expiration);
}
// unserializing array from mem cache
// if nothing found like first time and after a minute, then add key to the table
if (!($MY_SESSION_TABLE = unserialize(load_mcache($_REQUEST['JSESSIONID'])))) {
// save something to cache on first page load because we didnt have anything
$MY_SESSION_TABLE['key1'] = date('m/d/Y H:i:s');
// using jsessionid as a mem cache key, serializing array and setting cache time to one minute
save_mcache($_REQUEST['JSESSIONID'], serialize($MY_SESSION_TABLE), 60);
}
// now my session table is available for a minute until its initialized again
print_r($MY_SESSION_TABLE);
Now for proper session functionality you need to add set and get methods or even better a small class for handling it. Little abstraction to the classes and you could choose what kind of session mechanism to use with same library on different web app scenarios.
Related
I've created a function to get the likes for my facebook page using the graph api. However, the level rate limit keeps on getting reached as it's being called on every request.
How would i cache this so it doesn't make the call every time?
The code i'm currently using is:
function fb_like_count() {
$id = '389320241533001';
$access_token = 'access token goes here';
$json_url ='https://graph.facebook.com/v3.2/'.$id.'?fields=fan_count&access_token='.$access_token;
$json = file_get_contents($json_url);
$json_output = json_decode($json);
if($json_output->fan_count) {
return like_count_format($json_output->fan_count);
} else{
return 0;
}
}
There are many cache mechanism in PHP that you can use depending on your project size.
I would suggest you to check memcached or Redis. These are in-memory cache mechanisms that are pretty fast and would help you to gain better performance.
You can read more about how to implement memcached here or for redis here.
The second and easier way is to use file caching. It works like this:
You send a request to Facebook API and when response is returned you save it to a file. When you want to send the second response you can check if there is any content in your file first and if there is you can return that directly to your application otherwise you will send the request to Facebook API
Simple integration is like this
if (file_exists($facebook_cache_file) && (filemtime($facebook_cache_file) > (time() - 60 * 15 ))) {
// Cache file is less than 15 minutes old but you can change this.
$file = file_get_contents($facebook_cache_file); // this holds the api data
} else {
// Our cache is out-of-date, so load the data from our remote server,
// and also save it over our cache for next time.
$response = getFacebookData() // get data from facebook and save into file
file_put_contents($facebook_cache_file, $response, LOCK_EX);
}
Anyway I would suggest you to use any PHP library for doing file cache.
Below you can find some that might be interesting to look at:
https://github.com/PHPSocialNetwork/phpfastcache
https://symfony.com/doc/current/components/cache.html
I have an application that i built in php 7 with the code-igniter framework and my problem is with the session data , storing and retrieving session data works fine , but occasionally when two people log in at close intervals , the session data for the first user is also retrieved for the second user, searched through the site , saw something similar here (wrong data in PHP session) that suggested that it might be a caching issue (my site uses nginx for caching) , but no concrete solutions were suggested. Any suggestions or Ideas will be appreciated.
Edit : Here is the section of my login library for authentication
public function login_account($email,$password)
{
$db = "db";
$data = array("login_mail" => sha1($email));
$query_result = $this->CI->m_eauth->get_login_password($data,$db);
$hash_password ="";
foreach($query_result->result_array() as $value)
{
$hash_password = $value['hash_password'];
$site_name = $value['hash_name'];
$account_type = $value['account_type'];
$site_match_id = $value['site_match_id'];
$site_levels = $value['levels'];
$site_roles = $value['roles'];
}
if(password_verify($password, $hash_password)){
// Success!
$session_data = array(
"site_id"=>$site_match_id,
"site_email"=>$email,
"site_name"=>$site_name,
"site_avatar"=>md5($email).".jpg",
"site_type"=>$account_type,
"site_levels"=>$site_levels,
"site_roles"=>$site_roles
);
$this->CI->session->set_userdata($session_data);
return "successful";
}
else{
// Invalid credentials
return "unsuccessful";
}
}
Let me add that the login works fine and individual sessions work just fine. But every now and then the problem i described happens , and i'ts quite confusing as i don't know where to look.
There's no real way to sugar coat this, sessions aren't some magical part of PHP that you enable you to just call session_start() and go about your day. If your application is leaking sessions then you haven't secured it properly and you need to fix it.
Session security is a pretty big deal, given that a hijacked session basically gives an attacker total access to someone else's account.
I would recommend you read the official PHP session docs and also consider implementing the Nginx userid module as an additional measure for identifying users.
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.
I'm having a problem with Symfony creating a new session on each page load, rather than carrying data across requests. The auto_start in the session section in the config.yml is set to false, and regular php sessions work fine. It's only when running in symfony that I get the problem.
For example, I created the test action:
public function sessionTestAction()
{
$s_Response = '<html><head></head><body><p>Foo</p></body></html>'; //Initialize response and headers
$a_Headers = array();
$i_StatusCode = 200;
$oSession = $this->get('session');
var_dump($oSession->all());
if(!$oSession->has('Test'))
{
$oSession->set('Test', 'Bar');
}
$oSession->save();
return new Response($s_Response, $i_StatusCode, $a_Headers);
}
The expected action is, that on the first page load, the var_dump will yield nothing, and that on any subsequent executions, it will contain Test=>Bar. However, it never gets that data across requests.
In addition, it creates a new session id for each request.
I am using Symfony v2.0.15, and PHP v5.4
Anyone have any ideas?
Edit:
I made some progress, I think. I made the following changes to the test action:
public function sessionTestAction()
{
//Initialize response and headers
$oRequest = $this->get('request');
$a_Headers = array();
if (isset($oRequest->headers->all()['cookie']))
{
$a_Headers['Set-Cookie'] = $oRequest->headers->all()['cookie'];
}
$i_StatusCode = 200;
$oSession = $oRequest->getSession();
$oSession->start();
$s_Response = print_r($oSession->all(), true);
if(!$oSession->has('Test'))
{
$oSession->set('Test', 'Bar');
}
$oSession->save();
$oResponse = new Response($s_Response, $i_StatusCode, $a_Headers);
return $this->render('Bundle:Default:index.html.twig', array('response' => $s_Response), $oResponse);
}
Where that twig file has just {{response|raw}}. It now holds the session for 2 out of 3 of the requests. However, on the third request, it's cleared.
Turned out the problem was, someone added a line to set a session cookie whenever the app.php was run, not knowing that symfony handled sessions itself, I guess. Problem solved.
I got this problem a couple times, its very annoying. So, let me describe possible solution.
Open dev environment - yourdomain.com/app_dev.php/ Try to refresh page a couple times. If you see session ID changed each time - it means that sessions are broken.
If you are using chrome (if not - you should, its the best for developers ;) ) - you can open developers tools (click F12).
Next, check Network tab, refresh page and locate your main request.
Check headers for your request - if should see "Cookie:PHPSESSID".
If you dont see - something wrong with cookies. In my case it was
framework:
session:
cookie_domain: mydomain.com