I'm using a Symfony 2 to generate my pages from data in a MySQL database. For most content, users have to be authenticated but the content itself does not change often and does not need to be customized for the users. So what's a good caching strategy for avoiding database calls while still maintaining the auth check?
Simply put, use Memcache to cache the SQL result-set for extended period of time.
Maybe this be too huge change, but the following scheme may be useful in the case:
Create several sets of pages, one for not-yet-authed users (let's put in the site root), and others for authenticated users that should see the same content (say, it two or more should see the same content when they are authenticated, then we'll create only one set for all of them), and put it into directory under root. Then form simple .htaccess/.htpasswd files for each of such 'for-authed-only' directory and then it'll be webserver's problem not your script.
Hope you got the idea. It is fuzzy to say, but will be easy to implement.
Example: say you care to allow only authenticated users to see page '/topsecret.html' on the site. Create dir (/authed), establish HTTP-auth on it, and put your topsecret.html into the dir (so it'll be '/authed/topsecret.html'). Now edit '/topsecret.html' and simple replace it's main content with 'sorry, please authenticate yourself' link that'll point to '/authed/topsecret.html'.
If you use Symfony2, you are using Doctrine2
if you use Doctrine2, caching should be enabled by default.
Choose your cache driver for your purposes and there should be no problem.
You might also be specifically interested in query result caching.
Do not use Doctrine without a metadata and query cache! Doctrine is
highly optimized for working with caches. The main parts in Doctrine
that are optimized for caching are the metadata mapping information
with the metadata cache and the DQL to SQL conversions with the query
cache. These 2 caches require only an absolute minimum of memory yet
they heavily improve the runtime performance of Doctrine. The
recommended cache driver to use with Doctrine is APC. APC provides you
with an opcode-cache (which is highly recommended anyway) and a very
fast in-memory cache storage that you can use for the metadata and
query caches
I solved this by using Zend_Cache inside the cacheable actions to store the rendered template result. I then create a new Response object from the cached content. If the cache is empty, I generate the content.
I thought of creating a plugin that checks for an annotation and stores the Response output automatically but it turned out that I only have 3-4 display actions that are cacheable and have very complex cache ID creation rules, so I put the caching logic directly into the controller code.
It appears that you have a lot of options for caching with symfony http://www.symfony-project.org/book/1_2/12-Caching (not for 2 but my guess is not a lot has changed).
You could put your heavy sql statements in its own script and turn caching on for that script
list:
enabled: on
with_layout: false # Default value
lifetime: 86400 # Default value
Further if you are sure that the generated tag won't change for a while you could use symfony to tell the user's browser not even to bother your server for the content which will cause the page to load nearly instananeously for the user.
$this->getResponse()->addCacheControlHttpHeader('max_age=1200'); // in seconds - less than 1 year seconds
Just make sure your max age is small enough that when something changes (say a code update) that the user doesn't get stuck with old page since there is no way to force them to request that page again short of changing the url.
Related
I'm working on an app using CakePHP, and I have some generic settings that admins can change that affect the whole site, but I'm not quite sure how to handle saving/editing the data. These settings are for site-control related things, such as enabling/disabling new user registrations, enabling/disabling creating of new posts/topics, etc...
Since these aren't specific to individual users and there is only 1 set of values for the entire site, is it more advantageous to just use an XML file or should I create a table (which would only have 1 row)?
If I go with the XML route, are there any security related issues I should be aware of?
I saw this post but the accepted answer was on a per-user basis. This is only 1 set for the entire site.
This sort of configuration is general best left inside a config file on disk.
Also, I wouldn't use XML. I would use JSON. It's much easier to deal with, and you get proper data types out of the box for normal things.
http://php.net/manual/en/function.json-encode.php
http://php.net/manual/en/function.json-decode.php
There are no special security issues to storing config on disk. Just keep it out of the web server's document root, like everything else that isn't intended to be loaded directly by the user. Your config and application code should be only writable by users with that privilege.
I think it should be added in database which make easier to make changes by administrators . It should be then cached and used for faster execution of settings. You can store cache in place you like and that is all you have to do.
Use http://book.cakephp.org/2.0/en/core-libraries/caching.html
I'm a little confused here.
I know that for every PHP request, the entire application is bootstrapped all over again.
Given this, how can a cache be effective, if all of the globals are reloaded for each and every request?
For example:
User calls URI/user/view/123. User 123 is loaded from a database and stored in $user.
Why would you cache the contents of $user - when you merely need to refer to the variable in order to get the contents?
Am I missing the point?
Thank you,
Its more like caching images, common database querys
For instance say your site has a lot of articles and each article has categories. And say you dont change categories very often, then using a cached result of a query of the categories table is preferable then doing the query. this is a simplified example.
Another example is with images, if your site needs like thumbnailed version of user photos that they have uploaded instead of having php use the GD library to rescale the image and etc just save a version of that thumbnail version and use it instead of running through the GD code again.
As always, an image is worth a thousand words, here it is :)
(source)
As you can see, you reload some PHP librairies (like the basic environment (Globals, Requests, Cookies, etc), but not everything (in this case, Security, Application, various libraries, Views).
You skip what can be cached ;)
I have a home page as index.php and it gives a list of 10 items/ products.
Now, I am using the same page as landing page for inward traffic from facebook.
The url looks like index.php?productID=Q231 This page displays the product carrying the specified ID only.
I am aware of PHP output caching but I am new. I have learned that if I cache index.php, it will serve the same cached file to all the inward traffic from facebook.
Is my understanding correct? I have searched a lot about this but i am not clear as to how would one go about caching with this instance.
Is there a a way to skip or bypass the server cache file/caching if there's a query string in the url?
I would greatly appreciate if anyone could give me some pointers.
It really depends on your caching model and how you handle this in your code.
If you are creating the whole thing using output buffering you may want to use a method such as:
Generate Cache key based on requested script and/or request parameters i.e. using productId in your case
Check to see if you have saved the output for a given key to some persistent store
If yes, output
If no, then use an output buffer, generate the contents, save to a persistent store and save under the generated cache index, and output
Googling brings up this rudimentary example:
http://www.devshed.com/c/a/PHP/Output-Caching-with-PHP/
if i'm not mistaken caching is not based on referrer. Internal php caching is only to optimize code, it will not cache, as ie. 'external' caching systems, like inbuild caching in smarty for example, output. I think you'd only need to 'disable' caching for browsers, which will mean, send the proper headers with header(...)
You are using output caching. Then you should clear cache when your facebook or twitter links called. IN codeigniter(Framework of PHP), I have done this by clearing cache.
In core PHP, I don't know how to clear cache. But there must be some methods to clear cache. So try for that.
Here some links may be useful to you.
How to clear browser cache with php?
http://php.net/manual/en/function.clearstatcache.php
http://www.dreamincode.net/forums/topic/6519-clear-cache/
As far as I understand it, when you turn on caching in smarty, smarty caches compiled templates. These compiled templates can then used to speed up rendering of the page. Wouldn't it be a good idea to run you own level of caching on top of your smarty application that goes like this.
if(a cache for this page exists){
-Don't run my application, don't include my files don't instantiate my classes.
-Send the cached version of this page to the user
-end the script here
}else{//if the cache for this page does not exist or is not current
- run my application as usual
-save all the output to a file for next time
}
The whenever somthing happens on my site that would update the content of the this page, eg the admin makes changes to the content of the site delete the cache file. I feel like I must be missing something here. This method would allow me to store an all html version of every page and send that when it is valid. It seems like this would drastically improve the speed of my site.
Edit: Ok so I have discovered that smarty does infact store a html version of my site. How do I prevent my application from running if the rest of my application from running if the cache is current. Do I just include and instantiate smarty first and do something like
if($smarty->usingcache())[
exit;
}
If your site were static, this would work. But in that case, you wouldn't need Smarty...
Suppose you update a record in your database. Then all pages in your site which contain output directly or indirectly affected by the update would have to be invalidated. How would you know which pages to invalidate?
How can you know what the page will look like until you do some request specific processing. Until you've checked your client's authentication status, performed some database queries ( or fetched cached results) to fetch recent information, you can't know if the most recently rendered page is the same as what would be rendered this time. Smarty solves this with this strategy:
Your app does all of it's domain/business logic in response to the request.
Your app populates the smarty template instance with template variables
Smarty generates a hash of the template and the template variables
If the hash is not in the cache, Smarty renders the template and caches it
If the hash is in the cache, Smarty returns the cached template instead of rendering
If the cache is full, smarty evicts an old, cached page to make room.
By default, Smarty uses the filesystem for the Cache, but it the caching strategy is compatible with any key-value store. In fact, plugins exist for other stores, such as this one for memcached.
I read this link :-
http://codeigniter.com/user_guide/general/caching.html
It is written that :-
When a page is loaded for the first time, the cache file will be written to your system/cache folder
and that we can cache a view by $this->output->cache(60);. But how does it actually work? What if regularly my users keep updating and deleting records as a result of which view changes very often. Will it show the modified data? or will the cache bring back the old stale data? (before inserts and updates)? If it automatically manages and brings fresh data from the database, then what is purpose of specifying the minutes in cache function?
Thanks in advance :)
The way codeigniter's caching works generally is this:
A page request is made. Codeigniter (before very much of the framework has even been loaded) does a hash of the current url and if it finds that filename in the cache directory, it serves that.
The only way you can get fresh data is to manually delete the files. When codeigniter doesn't find the file from the hash it generated, it dynamically creates the page.
Codeigniter's implementation is called "full page" caching, and as so, is limited in it's usefullness. There's a partial caching library I've looked into from Phil Sturgeon here: http://philsturgeon.co.uk/code/codeigniter-cache
Honestly, for most projects, full page caching really isn't all that useful. In fact, the projects that I need full page caching I don't even leave that up to codeigniter (I leave it to the webserver: it's way faster).
I'd guess what you're looking for is a partial caching method; most people would prefer this. Look into APC if you're using a single server or Memcached if you have multiple servers.
Good Luck.
But how does it actually work?
If a cached version exists that is younger than the cache time, that cached version will be outputted.
Will it show the modified data?
Eventually yes, but with a lag of $cache_time
What if regularly my users keep updating and deleting records as a result of which view changes very often.
Reduce the cache time or don't use caching at all