tractorcow / silverstripe-dynamiccache

Simple on the fly caching of dynamic content for Silverstripe
39 stars 27 forks source link

Silverstripe DynamicCache - Simple on the fly caching of dynamic content for Silverstripe

This module seamlessly and robustly caches page content, allowing subsequent requests to bypass server heavy operations such as database access.

Credits and Authors

Requirements

How it works

When a page is requested by a visitor the module will attempt to return any cached content / custom headers for that request before the database connection is initiated. If a cached copy exists and can be returned, this can save a huge amount of processing overhead.

If a cached copy does not exist, then the page will process normally, but the result will then be saved for later page requests.

This differs from StaticPublisher or StaticExporter in that there is no administration caching. The caching is done incrementally on a per-page request basis rather than up front. This distributes the caching task across several requests, adding only a trivial overhead to non-cached requests, but saving a huge amount of time at the administration level.

Whenever a page is published the entire cache is cleared for the sake of robustness.

This module will allow individual pages to opt-out of caching by specifying certain headers, and will ignore caching on ajax pages or direct requests to controllers (including form submissions) by checking for any url-segments that start with an uppercase letter.

Installation Instructions

composer require "tractorcow/silverstripe-dynamiccache" "4.2.*"
RewriteRule .* dynamiccache/cache-main.php?url=%1&%{QUERY_STRING} [L]

Configuration options

Configuration can be done by the normal Silverstripe built in configuration system. See dynamiccache.yml for the list of configurable options.

Cache Clearing

By default the cache will be cleared whenever a SiteTree or SiteConfig object is updated or deleted, including publishing or unpublishing. This will flush the entire cache at once.

In order to prompt additional cache flushing, it may be necessary to clear this cache in other circumstances.

If this should be done when an object is changed, you should add the DynamicCacheDataObjectExtension extension to that type.

If this should be done in response to a conditional, or non-dataobject related action, then you can explicitly flush the cache with the below code:

DynamicCache::inst()->clear();

Additionally, if you are logged in (or are in dev mode) the cache can be flushed by adding the 'cache=flush' query parameter. E.g.

http://www.app.com/?cache=flush

Customising Cache Behaviour

If you extend DynamicCache you can hook into two additional methods. A helper extension class DynamicCacheExtension can be used here to get started.

The below example will allow the cache to be bypassed if a certain session value is set, and segments the cache between mobile / non-mobile users (assuming silverstripe/mobile module is installed).


    class CacheCustomisation extends DynamicCacheExtension {
        public function updateEnabled(&$enabled) {
            // Disable caching for this request if a user is logged in
            if (Member::currentUserID()) $enabled = false;

            // Disable caching for this request if in dev mode
            elseif (Director::isDev()) $enabled = false;

            // Disable caching for this request if we have a message to display
            // or the request shouldn't be cached for other reasons
            elseif (Session::get('StatusMessage') || Session::get('Uncachable')) $enabled = false;
        }

        public function updateCacheKeyFragments(array &$fragments) {
            // For any url segment cache between mobile and desktop devices.
            $fragments[] = MobileBrowserDetector::is_mobile() ? 'mobile' : 'desktop';
        }
    }

License

Copyright (c) 2013, Damian Mooyman All rights reserved.

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.