Wallogit.com
2017 © Pedro Peláez
Easy to use, flexible memoizer with optional automated cacheing
Please consider using the illuminate cache package., (*1)
Our Simple Cacheing Memoizer is a flexible memoizer that can also optionally be combined with a cache to automatically memoize results of calling functions., (*2)
We've implemented one example of the latter function using cyber-duck/laravel-cacheing-memoizer which adds it to Laravel for you, but it can also be used in other frameworks - it was originally written for a legacy site that is being upgraded from Codeigniter to Laravel gradually, and works fine in both., (*3)
add, (*4)
use CyberDuck\CacheingMemoizer\MemoizesResults, (*5)
to your class., (*6)
This will give your class extra methods, the most important of which is memoize., (*7)
Memoize takes two or more arguments., (*8)
The first are the building blocks of the memoization key. The second is a function that will return the value to be memoized. The third and any subsequent arguments will be passed to the function when it is invoked., (*9)
Memoization is by default unique to the object, but it is also possible to use singletonMemoize
which is exactly the same as memoize except it memoizes the value of the result in one sningleton, (*10)
Important note: Because this is framework agnostic, the memoizer has to manage the singleton itself. So it may not be the
'same' singleton as your framework preservers. If this is important then over-write the singletonMemoize method., (*11)
There is also a globallyMemoize method. This essentially memoizes the result with that key for any object., (*12)
You may also use the memoization features with automated cacheing. This requires two steps:, (*13)
Setup the memoizer to use the cache by:, (*14)
CyberDuck\CacheingMemoizer\CacheingMemoizer::setCacheRetrievalFunction with a callable which should accept one
argument - the cache key - and return the result if there is a cache hit, null other wise. CyberDuck\CacheingMemoizer\CacheingMemoizer::addShutdownFunction at least once with a callable which should accept
two arguments - key, then value, which will write to the cacheCyberDuck\CacheingMemoizer\CacheingMemoizer::shutdown to be called at the end of the request.(if you are using Laravel, cyber-duck/laravel-cacheing-memoizer will do this for you), (*15)
globallyMemoizeWithCache in the same way as globallyMemoize
See source code. Documentation coming. forget and getMemoizeKey are the main ones, their import hopefully obvious., (*16)
Certainly, here's a simple example of using it in one class to avoid the overhead of an expensive call:, (*17)
public function getPackageAttribute() { return $this->memoize('package', function () { return package()->create(['code' => $this->PackageTypeCode]); }); }
Here's an example of how quickly we added memoization + cacheing to a function in 5+ year old legacy code, without having to rewrite anything fresh. The original function looked like:, (*18)
public function find_all($params = array(), $skip = array('page', 'limit', 'sort-by'))
{
$this->db->select('waOrg.OrgID, waOrg.OrgName, waOrg.PackageTypeCode, waOrg.HasGallery, waOrg.HasShowReel, waOrg.AllowSearchResultsPageLogo');
$this->db->join($this->dbn.'[wlEntry]', 'wlEntry.OrgID = waOrg.OrgID');
$this->db->join($this->dbn_live.'[wpCountry]', 'wpCountry.Country = waOrg.Country', 'left');
$this->db->group_by('waOrg.OrgID, waOrg.OrgName, waOrg.PackageTypeCode, waOrg.HasGallery, waOrg.HasShowReel, waOrg.AllowSearchResultsPageLogo');
$this->db->distinct();
$this->_apply_filters($params, $skip);
$query = $this->db->get($this->dbn.'[waOrg] waOrg');
if(count($query->result()) > 0)
{
return count($query->result());
}
return false;
}
With automated memoization + cacheing it now looks like:, (*19)
public function find_all($params = array(), $skip = array('page', 'limit', 'sort-by')) { return $this->globallyMemoizeWithCache(['org.find.all', $params, $skip], function($params, $skip){ $this->db->select('waOrg.OrgID, waOrg.OrgName, waOrg.PackageTypeCode, waOrg.HasGallery, waOrg.HasShowReel, waOrg.AllowSearchResultsPageLogo'); $this->db->join($this->dbn.'[wlEntry]', 'wlEntry.OrgID = waOrg.OrgID'); $this->db->join($this->dbn_live.'[wpCountry]', 'wpCountry.Country = waOrg.Country', 'left'); $this->db->group_by('waOrg.OrgID, waOrg.OrgName, waOrg.PackageTypeCode, waOrg.HasGallery, waOrg.HasShowReel, waOrg.AllowSearchResultsPageLogo'); $this->db->distinct(); $this->_apply_filters($params, $skip); $query = $this->db->get($this->dbn.'[waOrg] waOrg'); if(count($query->result()) > 0) { return count($query->result()); } return false; }, $params, $skip); }