The cron-job way is definitely the easiest one and it's good enough for normal use cases.
If the changes the users makes affects the other users (for example, make a fire, which, if let unattended it would burn other player's houses in the meantime), then you can't use the first idea. Otherwise having some sort of "TODO" lists that get completed (finish the tasks) when he relogs is fine.
You ask about 'too much for the server'. You don't have to worry about. If you keep the cron jobs constant and frequent enough, you'll have a better performance. That is, doing small things over a long period is better than cramming many into fewer time. The overhead of invoking the cron job, compared to the actual work done might be negligible.
Almost all other ideas base on repeating themselvesHowever, just like a cron job would do.here are two more ways that come to my mind right now:
- Windows Azure. There is a PHP SDK (https://github.com/windowsazure/azure-sdk-for-php). To be more specific you'd need to create an Azure Worker Role which is deployed there. Then, from PHP you'd post some tasks to be done in a Queue container. The Worker role polls for remaining tasks and executes them.
- Node.js (http://nodejs.org/). You can create a server that, just like the Windows Azure Worker role, awaits for tasks from the PHP scripts. Then, you'd just have to move the logic of time-based work in those tasks. You can look for more info in here: http://dev.iron.io/worker/languages/nodejs/