Answers.Body: <h3>1. CRM_Utils_Cache::create()</h3>
  
  <p>When looking through the list of cache drivers, you see options like <code>Memcache</code>, <code>Memcached</code>, and <code>Redis</code>. Generally there's little reason why a deployment would use all three -- rather, the typical question this:</p>
  
  <ul>
  <li>Do we have <em>any</em> kind of high-speed/shared/memory-based cache? If so, use it. </li>
  <li>Do we have any kind of SQL-backed cache? If so, use it.</li>
  <li>Otherwise, use an ephemeral <code>array()</code> (for the duration each request)</li>
  </ul>
  
  <p>In v4.7, <code>CRM_Utils_Cache::create()</code> is a factory function which accepts an ordered list of drivers, and it picks the first one that's usable, e.g.</p>
  
  <pre><code>$myCache = CRM_Utils_Cache::create(array(
    'name' =&gt; 'somethingsomething',
    'type' =&gt; array('*memory*', 'SqlGroup', 'ArrayCache'),
  ));
  </code></pre>
  
  <p>This aims to address the typical use-case by making it unnecessary for the admin to configure anything extra for your specific extension.</p>
  
  <p>Your extension would need to retain a copy of that cache object, e.g.</p>
  
  <pre><code>function myextension_cache() {
    if (!isset(Civi::$statics['myextension_cache'])) {
      Civi::$statics['myextension_cache'] = CRM_Utils_Cache::create(array(
        'name' =&gt; 'somethingsomething',
        'type' =&gt; array('*memory*', 'SqlGroup', 'ArrayCache'),
      ));
    }
    return Civi::$statics['myextension_cache'];
  }
  </code></pre>
  
  <p>I believe this answers the typical requirement/issue when someone wants to configure the extension's cache, but it doesn't literally answer the question...</p>
  
  <h3>2. Named services and caching</h3>
  
  <p>The <a href="http://symfony.com/doc/current/service_container.html" rel="noreferrer">Symfony service container</a> is a general-purpose tool for naming and tracking a bunch of objects -- cache services, database services, entity-repositories, etc. Rather than have a hundred functions like <code>myextension_cache()</code> which hard-code the factory, we put all the factories together in the container. This pattern improves our leverage; in principle, you can expose the container to different processes, e.g.</p>
  
  <ul>
  <li>Reading multiple YAML/XML files to configure the container</li>
  <li>Allowing extensions/hooks to alter the container</li>
  <li>Allowing site admins to alter the container</li>
  <li>Allowing dev-tools and admin-tools to inspect the container</li>
  </ul>
  
  <p>For this reason, new caches in core tend to be <a href="https://github.com/civicrm/civicrm-core/blob/4.7.14/Civi/Core/Container.php#L159" rel="noreferrer">created through the container</a>, e.g.</p>
  
  <ul>
  <li><a href="https://github.com/civicrm/civicrm-core/blob/4.7.14/Civi.php#L28" rel="noreferrer"><code>Civi::cache()</code></a> is equivalent to <code>Civi::container()-&gt;get('cache.default')</code></li>
  <li><a href="https://github.com/civicrm/civicrm-core/blob/4.7.14/Civi.php#L28" rel="noreferrer"><code>Civi::cache('js_strings')</code></a> is equivalent to <code>Civi::container()-&gt;get('cache.js_strings')</code></li>
  </ul>
  
  <p>However, at this point, the container in Civi needs improvement. For example, you can alter the container via <a href="https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_container" rel="noreferrer"><code>hook_civicrm_container</code></a>, but there's no YAML/XML/annotation mechanism for updating the container, and there's no mechanism for site-admins to modify services via config file (<code>civicrm.settings.php</code>). </p>
  
  <p>The long-term goal is to shift more service-management into a container so that questions like "How does a site admin customize service X?" have a categorical answer. Improving the container is very much patch-welcome.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-12-30T19:40:29.270Z
Answers.LastActivityDate: 2016-12-30T19:45:30.827Z
Answers.LastEditDate: 2016-12-30T19:45:30.827Z
Answers.UserDisplayName: Tim Otten
Body: <p>CiviCRM contains some useful caching infrastructure (<a href="https://wiki.civicrm.org/confluence/display/CRMDOC/Cache+Reference" rel="nofollow noreferrer">confluence wiki</a> and <a href="https://civicrm.stackexchange.com/questions/7340/how-can-i-use-civicrms-cache-table">related question</a>).</p>
  
  <p>If I am creating a module and I would like to allow users to override the default <code>Civi::cache()</code> <strong>specifically for this extension</strong> how should I do that?</p>
  
  <p>I think putting some settings (maybe a factory function?) in the <code>civicrm.settings.php</code> would be the best way? Is this correct? And any examples?</p>
  
  <p>I'm thinking I could just put something like this in my code:</p>
  
  <p><code>
  if (function_exists('myextension_cach_factory')) {
    $cache = myextension_cach_factory();
  }
  else {
    $cache = Civi::cache();
  }
  </code></p>
  
  <p>Then the settings file could contain something like</p>
  
  <p><code>
  // civicrm.settings.php
  function myextension_cache_factory() {
    return new CRM_Utils_Cache_SerializeCache(array());
  }
  </code></p>
  
  <p>or maybe even:</p>
  
  <p><code>
  //civicrm.settings.php
  function myextension_cache_factory() {
    return new CRM_Utils_Cache_Memcached(array(
      'host' =&gt; 'localhost',
      'port' =&gt; 11211,
      'timeout' =&gt; 3600,
      'prefix' =&gt; 'mec_',
    ));
  }
  </code></p>
  
  <h2>Background:</h2>
  
  <p><code>$civicrm_root/CRM/Utils/Cache/Interface.php</code> defines a minimal standard interface for caching with get(), set(), delete() and flush() methods.</p>
  
  <p><code>$civicrm_root/CRM/Utils/Cache/</code> has these useful looking implementations:</p>
  
  <p><code>
  APCcache.php
  ArrayCache.php
  Memcache.php
  Memcached.php
  NoCache.php
  SerializeCache.php 
  SqlGroup.php
  </code></p>
  
Tags: <extension><php><cache>
Title: How to let extension users choose cache system?
ThreadText: # How to let extension users choose cache system?
  
  (Asked by: username_0 on 2016-12-29)
  
  CiviCRM contains some useful caching infrastructure ([confluence wiki](https://wiki.civicrm.org/confluence/display/CRMDOC/Cache+Reference) and [related question](https://civicrm.stackexchange.com/questions/7340/how-can-i-use-civicrms-cache-table)).
  
  If I am creating a module and I would like to allow users to override the default `Civi::cache()` **specifically for this extension** how should I do that?
  
  I think putting some settings (maybe a factory function?) in the `civicrm.settings.php` would be the best way? Is this correct? And any examples?
  
  I'm thinking I could just put something like this in my code:
  
  `if (function_exists('myextension_cach_factory')) {
  $cache = myextension_cach_factory();
  }
  else {
  $cache = Civi::cache();
  }`
  
  Then the settings file could contain something like
  
  `// civicrm.settings.php
  function myextension_cache_factory() {
  return new CRM_Utils_Cache_SerializeCache(array());
  }`
  
  or maybe even:
  
  `//civicrm.settings.php
  function myextension_cache_factory() {
  return new CRM_Utils_Cache_Memcached(array(
  'host' => 'localhost',
  'port' => 11211,
  'timeout' => 3600,
  'prefix' => 'mec_',
  ));
  }`
  
  ## Background:
  
  `$civicrm_root/CRM/Utils/Cache/Interface.php` defines a minimal standard interface for caching with get(), set(), delete() and flush() methods.
  
  `$civicrm_root/CRM/Utils/Cache/` has these useful looking implementations:
  
  `APCcache.php
  ArrayCache.php
  Memcache.php
  Memcached.php
  NoCache.php
  SerializeCache.php
  SqlGroup.php`
  
  **Tags:** extension, php, cache
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2016-12-30. Score: 4 | Accepted answer
  
  1. CRM_Utils_Cache::create()
  When looking through the list of cache drivers, you see options like Memcache, Memcached, and Redis. Generally there's little reason why a deployment would use all three -- rather, the typical question this:
  
  Do we have any kind of high-speed/shared/memory-based cache? If so, use it. 
  Do we have any kind of SQL-backed cache? If so, use it.
  Otherwise, use an ephemeral array() (for the duration each request)
  
  In v4.7, CRM_Utils_Cache::create() is a factory function which accepts an ordered list of drivers, and it picks the first one that's usable, e.g.
  $myCache = CRM_Utils_Cache::create(array(
    'name' => 'somethingsomething',
    'type' => array('*memory*', 'SqlGroup', 'ArrayCache'),
  ));
  
  This aims to address the typical use-case by making it unnecessary for the admin to configure anything extra for your specific extension.
  Your extension would need to retain a copy of that cache object, e.g.
  function myextension_cache() {
    if (!isset(Civi::$statics['myextension_cache'])) {
      Civi::$statics['myextension_cache'] = CRM_Utils_Cache::create(array(
        'name' => 'somethingsomething',
        'type' => array('*memory*', 'SqlGroup', 'ArrayCache'),
      ));
    }
    return Civi::$statics['myextension_cache'];
  }
  
  I believe this answers the typical requirement/issue when someone wants to configure the extension's cache, but it doesn't literally answer the question...
  2. Named services and caching
  The Symfony service container is a general-purpose tool for naming and tracking a bunch of objects -- cache services, database services, entity-repositories, etc. Rather than have a hundred functions like myextension_cache() which hard-code the factory, we put all the factories together in the container. This pattern improves our leverage; in principle, you can expose the container to different processes, e.g.
  
  Reading multiple YAML/XML files to configure the container
  Allowing extensions/hooks to alter the container
  Allowing site admins to alter the container
  Allowing dev-tools and admin-tools to inspect the container
  
  For this reason, new caches in core tend to be created through the container, e.g.
  
  Civi::cache() is equivalent to Civi::container()->get('cache.default')
  Civi::cache('js_strings') is equivalent to Civi::container()->get('cache.js_strings')
  
  However, at this point, the container in Civi needs improvement. For example, you can alter the container via hook_civicrm_container, but there's no YAML/XML/annotation mechanism for updating the container, and there's no mechanism for site-admins to modify services via config file (civicrm.settings.php). 
  The long-term goal is to shift more service-management into a container so that questions like "How does a site admin customize service X?" have a categorical answer. Improving the container is very much patch-welcome.
  
  
  ---
  
  