Skip to content

Instantly share code, notes, and snippets.

@jlem
Created August 25, 2015 03:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlem/43f719d668bdf50e4043 to your computer and use it in GitHub Desktop.
Save jlem/43f719d668bdf50e4043 to your computer and use it in GitHub Desktop.
Eloquent model caching
<?php
class Member extends Model implements CurrentMember
{
use ModelCache;
public function getLeaguePlayer(SectionInterface $section)
{
return $this->cache(function(SectionInterface $section) {
return $this->leaguePlayers()
->where('section_id', $section->getID())
->first();
});
}
}
<?php
trait ModelCache
{
protected $dataCache = [];
/**
* Gets the cached result by key, or executes the closure if cache key does not exist
* @param \Closure $closure
* @return mixed
*/
public function cache(\Closure $closure)
{
// This is so we know the name of the function call, and the arguments
// We want to md5 serialize these so the cache is unique to the arguments
$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT,2)[1];
$key = $backtrace['function'];
$args = $backtrace['args'];
$key = $key . '.' . md5(serialize($args));
if (!array_key_exists($key, $this->dataCache)) {
$this->dataCache[$key] = call_user_func_array($closure, $args);
}
return $this->dataCache[$key];
}
/**
* Returns the entire cache
* @return array
*/
public function getCache()
{
return $this->dataCache;
}
}
@jlem
Copy link
Author

jlem commented Aug 25, 2015

Note that this is not a cache as in a time-based cache - it's just a registry cache, so that subsequent calls to $member->getLeaguePlayer($section) in the remainder of the request cycle don't result in repeated queries.

This is identical in behavior to how Eloquent relations cache their results instead of repeating queries.

It would be great to have something more baked into Eloquent such that you don't have to do gross wrapping in a callback function all the time.

Perhaps an array property like:

$cacheable = [
    'getLeaguePlayers',
    'fooBarMethod'
];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment