Yes, you can write it in PHP, and PHP won't be invoked unless the page is missing. It's actually quite easy to create a pull-based page caching system.
Come up with a scheme for translating your database references into unique filenames. Those should be .html files, not .php files. (An example is below.)
Write a PHP script that looks at the value of $REDIRECT_URL, which should be in the format you just invented. Parse that string. Use it to invoke your dynamic page script. Save the results to the appropriate filename, and pass them through to the user.
Tell Apache to use that error-handling script as the 404 handler. This can be done globally, or on a per-directory basis by using .htaccess files.
This is basically how the Vignette StoryServer engine works; it is a 404 handler that is invoked when a page is missing. Vignette does this with filenames that look like 0,2097,1-1-1515,00.html. Your scheme might look different.
Since you are saving these "error-generated" files with .html extensions, the PHP parser will NOT be invoked when a page is found. This will cut system load dramatically.
The first viewer of any particular database selection will invoke the PHP system. The second and subsequent viewers will not.
Obviously, if you have a dynamic data set, you are going to have to flush these .html files somehow. You might write triggers into your data-management or content-management system that delete the .html files when the underlying data is altered. Or, if it's appropriate, you might write a cron job to clean out the cache directories on some regular schedule.
Note that this approach is very different than that of the Zend Accelerator, which solves a different problem. The Zend Accelerator (formerly known as Zend Cache) stores bytecode-compiled versions of your script in server memory space. This accelerates the execution of PHP scripts, particularly complex ones, but it does nothing to address database access load. And merely asking Apache to look for <? and ?> tags roughly doubles page-delivery time.
If you are essentially delivering large quantities of common, relatively static data, the pull-based page-caching system might be your best bet. If you are delivering 1:1-tailored content for each individual user, page-level caching will not get you much help.
If you want to get fancy, you could think about applying pull-based cache technology to page modules rather than complete pages. Vignette uses that technique extensively; it allows the top-level delivery to be dynamic and customized, but if the components are shared across large numbers of users (latest headline clusters, for instance), the you can avoid hitting a database.