tags:

views:

1683

answers:

8
+8  Q: 

PHP object caching

In ASPNET, I grew to love the Application and Cache stores. They're awesome. For the uninitiated, you can just throw your data-logic objects into them, and hey-presto, you only need query the database once for a bit of data.

By far one of the best ASPNET features, IMO.

I've since ditched Windows for Linux, and therefore PHP, Python and Ruby for webdev. I use PHP most because I dev several open source projects, all using PHP.

Needless to say, I've explored what PHP has to offer in terms of caching data-objects. So far I've played with:

  1. Serializing to file (a pretty slow/expensive process)
  2. Writing the data to file as JSON/XML/plaintext/etc (even slower for read ops)
  3. Writing the data to file as pure PHP (the fastest read, but quite a convoluted write op)

I should stress now that I'm looking for a solution that doesn't rely on a third party app (eg memcached) as the apps are installed in all sorts of scenarios, most of which don't have install rights (eg: a cheap shared hosting account).

So back to what I'm doing now, is persisting to file secure? Rule 1 in production server security has always been disable file-writing, but I really don't see any way PHP could cache if it couldn't write. Are there any tips and/or tricks to boost the security?

Is there another persist-to-file method that I'm forgetting?

Are there any better methods of caching in "limited" environments?

A: 

It's in theory possible to store objects in sessions. That might get you past the file writing disabled problem. Additionally you could store the session in a mysql memory backed table to speed up the query.

Linor
That's an idea but it's not big enough. Imagine 1000 users landed on the site and requested the same data five times. Normally, that's 5000 DBIOs. With your method, it's 1000 (and a lot of duplicate data!) With ASPNET's Cache (and the methods I mentioned above), it's 1. That's what I'm striving for.
Oli
+9  A: 

Serializing is quite safe and commonly used. There is an alternative however, and that is to cache to memory. Check out memcached and APC, they're both free and highly performant. This article on different caching techniques in PHP might also be of interest.

Eran Galperin
I wish I could guarantee access to memcached but due to the nature of these projects, I can't control deployment... And I can't really set it as a requirement. Good to know that allowing PHP to write isn't the end of the world.
Oli
I'd argue (and did http://stackoverflow.com/questions/126917#127165) the *quite safe* bit. There's nothing inherently unsafe about serializing and writing, but doing so in a shared hosting environment is far from ideal.
Alan Storm
Encoderer
APC is not just a bytecode cache. It also has cache-to-memory capabilities, similar to memcache.
Eran Galperin
A: 

Some hosting places may have APC compiled in.. That would allow you to store the objects in memory.

DreamWerx
A: 

If you have access to the Database Query Cache (ie. MySQL) you could go with serializing your objects and storing them in the DB. The database will take care of holding the query results in memory so that should be pretty fast.

Polygraf
+2  A: 

What I always do if I have to be able to write is to ensure I'm not writing anywhere I have PHP code. Typically my directory structure looks something like this (it's varied between projects, but this is the general idea):

project/
  app/
  html/
    index.php
    data/
  cache/

app is not writable by the web server (neither is index.php, preferably). cache is writable and used for caching things such as parsed templates and objects. data is possibly writable, depending on need. That is, if the users upload data, it goes into data.

The web server gets pointed to project/html and whatever method is convenient is used to set up index.php as the script to run for every page in the project. You can use mod_rewrite in Apache, or content negotiation (my preference but often not possible), or whatever other method you like.

All your real code lives in app, which is not directly accessible by the web server, but should be added to the PHP path.

This has worked quite well for me for several projects. I've even been able to get, for instance, Wikimedia to work with a modified version of this structure.

Oh... and I'd use serialize()/unserialize() to do the caching, although generating PHP code has a certain appeal. All the templating engines I know of generate PHP code to execute, making post-parse very fast.

Michael Johnson
+3  A: 

Re: Is there another persist-to-file method that I'm forgetting?

It's of limited utility but if you have a particularly beefy database query you could write the serialized object back out to an indexed database table. You'd still have the overhead of a database query, but it would be a simple select as opposed to the beefy query.

Re: Is persisting to file secure? and cheap shared hosting account)

The sad fact is cheap shared hosting isn't secure. How much do you trust the 100,500, or 1000 other people who have access to your server? For historic and (ironically) security reasons, shared hosting environments have PHP/Apache running as a unprivileged user (with PHP running as an Apache module). The security rational here is if the world facing apache process gets compromised, the exploiters only have access to an unprivileged account that can't screw with important system files.

The bad part is, that means whenever you write to a file using PHP, the owner of that file is the same unprivileged Apache user. This is true for every user on the system, which means anyone has read and write access to the files. The theoretical hackers in the above scenario would also have access to the files.

There's also a persistent bad practice in PHP of giving a directory permissions of 777 to directories and files to enable the unprivileged apache user to write files out, and then leaving the directory or file in that state. That gives anyone on the system read/write access.

Finally, you may think obscurity saves you. "There's no way they can know where my secret cache files are", but you'd be wrong. Shared hosting sets up users in the same group, and most default file masks will give your group users read permission on files you create. SSH into your shared hosting account sometime, navigate up a directory, and you can usually start browsing through other users files on the system. This can be used to sniff out writable files.

The solutions aren't pretty. Some hosts will offer a CGI Wrapper that lets you run PHP as a CGI. The benefit here is PHP will run as the owner of the script, which means it will run as you instead of the unprivileged user. Problem averted! New Problem! Traditional CGI is slow as molasses in February.

There is FastCGI, but FastCGI is finicky and requires constant tuning. Not many shared hosts offer it. If you find one that does, chances are they'll have APC enabled, and may even be able to provide a mechanism for memcached.

Alan Storm
FastCGI isn't terribly slow - slower than mod_php but better. Thanks for the explanation though. +1
Oli
Right, but it's hard to find in cheap shared hosting.
Alan Storm
A: 

You don't spell out -why- you're trying to cache objects. Are you trying to speed up a slow database query, work around expensive object instantiation, avoid repeated generation of complex page, maintain application state or are you just compulsively storing away objects in case of a long winter?

The best solution, given the atrocious limitations of most low-cost shared hosting, is going to depend on what you're trying to accomplish. Going for bottom of the barrel shared-hosting means you have to accept that you won't be working with the best tools. The numbers are hard to quantify, but there's a trade off between hosting costs, site performance & developer time (ie - fast, cheap or easy).

Sean McSomething
+1  A: 

I had a similar problem, and thus wrote a solution, a memory cache written in PHP. It only requires the PHP build to support sockets. Other then that, it is a pure php solution and should run just fine on Shared hosting.

http://code.google.com/p/php-object-cache/

bucabay