Cache PHP Pages in Simple Way with Nginx

Cache PHP Pages in Simple Way with Nginx

Caching is an important part in scaling a website or enhance some old website. Here is a tutorial how to using lines of code to caching PHP Page.
For this tutorial, your web server have to be an Nginx server + PHP-FPM + PHP environment. Sorry to Apache use this time. So… How’s work? It is simple.
We will use ob_get_content() function to crap all the output in the buffer generated by PHP, and then we write the output a HTML file, and then we using Nginx try_files features,
sending the cached HTML file to the client to reduce your PHP-FPM overhead and make your general output become static.

If you don’t know what is Nginx try_files features, please take a look

Checks for the existence of files in order, and returns the first file that is found. A trailing slash indicates a directory – $uri /. In the event that no file is found, an internal redirect to the last parameter is invoked.

Quote From //wiki.nginx.org/HttpCoreModule#try_files

Pros:

  • No dependencies in PHP and Nginx
  • Reduce the Overhead in PHP-FPM
  • Nginx serves static file is super fast, so we output as HTML file’

Cons:

  • as it is simple way, not suitable for user-driven website, that means if your website content is depend on your user, the cache will be the first user that reached the page.

What type of site will be suitable for direct use then?

  • blog
  • online categories

Ok, Let’s get started!

  1. To use ob_get_content() function, you have to add ob_start() before any output.

    # your_header.php
    <?php
    
    // make the output to buffer
    ob_start(); 
    
  2. and then, add the end of your php output code

    Raw PHP implement:

    ... blah blah blah
    </body>
    </html>
    <?php
    
    // give a name to the buffer output;
    $html_output = ob_get_content();
    
    // clear the buffer, it is useful if your server is not fast
    ob_end_clean();
    
    \\ 
    

    MVC PHP Framework implement:

    <?php
    
    namespace Controller;
    
    class MyController extends base_controller {
    
        public function index(){
    
            // load data from database    
            $data = PageModel::find(...);
    
            // make the output to buffer
            ob_start(); 
    
            // out put the html
            $this->load->view('MyController/index', $data);
    
            // give a name to the buffer output;
            $html_output = ob_get_content();
    
            // clear the buffer, it is useful if your server is not fast
            ob_end_clean();
    
        }
    }
    
  3. Now, $html_output is your whole html page, write it in your file.

    # Create a helper function for writing file
    
    /**
     * Write File / Clone from Codeigniter
     * 
     * @link    https://github.com/EllisLab/CodeIgniter/blob/develop/system/helpers/file_helper.php
     * @author  EllisLab Dev Team
     * Writes data to the file specified in the path.
     * Creates a new file if non-existent.
     *
     * @access  public
     * @param   string  path to file
     * @param   string  file data
     * @return  bool
     *
     **
    if ( ! function_exists('write_file'))
    {
        function write_file($path, $data, $mode = 'wr+')
        {
            if ( ! $fp = @fopen($path, $mode))
            {
                return FALSE;
            }
    
            flock($fp, LOCK_EX);
            fwrite($fp, $data);
            flock($fp, LOCK_UN);
            fclose($fp);
    
            return TRUE;
        }
    }
    
    # and write the output to our cache folder
    write_file('/path/to/cache/'.$_SERVER['REQUEST_URI'].'.html', $html_output);
    
  4. the file will be saved base on the request URI. so we just use try_files in Nginx config. Here is the sample

    server {
        # listen 80 default_server deferred; # for Linux
        # listen 80 default_server accept_filter=httpready; # for FreeBSD
        listen 80;
    
        # The host name to respond to
        server_name domain.com;
    
        # Path for static files
        root /var/www/server_root;
    
    
        #index file
        index index.php;
    
        #Specify a charset
        charset utf-8;
    
        location / {
            autoindex on;
            try_files /cache/$uri.html $uri $uri/ /index.php?$args;
        }
    }
    
  5. try to fresh your page, and see if there is file saved on your cache folder. done!

File Structure

 webroot /
 |- about_us.php
 |- term.php
 +- cache/
    |- about_us.php.html
    |- term.php.html

Conculsion

One your cached files are store, Nginx will send the cache file to the client directly, it will no long pass to PHP-FPM to process. For those non-update offen pages, it may be a good method to cache.
Your server now should have more square resources to handle other process. Let’s try out and comment below share your opinion.

Subscription

We will send you a newsletter weekly, includes Coder Read, weekly resources summary, library / application updates & some freebies.

Related Articles