Skip to content

Commit 3d41773

Browse files
author
Corey McCormick
committed
First
1 parent ce73e35 commit 3d41773

File tree

9 files changed

+808
-0
lines changed

9 files changed

+808
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.idea
2+
/vendor
3+
composer.lock

composer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "simplesoftwareio/simple-cache",
3+
"description": "An easy to use caching trait for Laravel's Eloquent Models.",
4+
"license": "MIT",
5+
"authors": [
6+
{
7+
"name": "Simple Software LLC",
8+
"email": "support@simplesoftware.io"
9+
}
10+
],
11+
"minimum-stability": "stable",
12+
"require-dev": {
13+
"phpunit/phpunit": "5.5.*",
14+
"mockery/mockery": "0.9.*"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"SimpleSoftwareIO\\Cache\\": "src/"
19+
}
20+
},
21+
"require": {
22+
"illuminate/database": "~5",
23+
"illuminate/cache": "~5"
24+
}
25+
}

phpunit.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit backupGlobals="false"
3+
backupStaticAttributes="false"
4+
bootstrap="./vendor/autoload.php"
5+
colors="true"
6+
convertErrorsToExceptions="true"
7+
convertNoticesToExceptions="true"
8+
convertWarningsToExceptions="true"
9+
processIsolation="false"
10+
stopOnFailure="false"
11+
syntaxCheck="false"
12+
>
13+
<testsuites>
14+
<testsuite name="Application Test Suite">
15+
<directory>./tests/</directory>
16+
</testsuite>
17+
</testsuites>
18+
</phpunit>

src/Cacheable.php

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
3+
namespace SimpleSoftwareIO\Cache;
4+
5+
trait Cacheable
6+
{
7+
/**
8+
* Configures the cache store to be used.
9+
*
10+
* @var
11+
*/
12+
protected $cacheStore;
13+
14+
/**
15+
* Determines the length to cache a result.
16+
*
17+
* @var int
18+
*/
19+
protected $cacheLength = 30;
20+
21+
/**
22+
* Determines if the cache should be busted
23+
* on inserts/updates/deletes.
24+
*
25+
* @var bool
26+
*/
27+
protected $cacheBusting = false;
28+
29+
/**
30+
* Overrides the default QueryBuilder to inject the Cache methods
31+
*
32+
* @return QueryCacheBuilder
33+
*/
34+
protected function newBaseQueryBuilder()
35+
{
36+
$conn = $this->getConnection();
37+
38+
$grammar = $conn->getQueryGrammar();
39+
40+
return new QueryCacheBuilder($this->queryCache(), $conn, $grammar, $conn->getPostProcessor());
41+
}
42+
43+
/**
44+
* Generates a new QueryCache
45+
*
46+
* @return QueryCache
47+
*/
48+
protected function queryCache()
49+
{
50+
return new QueryCache($this->cacheStore, $this->cacheLength);
51+
}
52+
53+
/**
54+
* Flushes the cache on insert/update.
55+
*
56+
* @param array $options
57+
* @return void
58+
*/
59+
public function finishSave(array $options)
60+
{
61+
if ($this->cacheBusting) {
62+
$this->queryCache()->flush($this->getTable());
63+
}
64+
65+
parent::finishSave($options);
66+
}
67+
68+
/**
69+
* Flushes the cache on deletes.
70+
*
71+
* @return bool|null
72+
*/
73+
public function delete()
74+
{
75+
if ($this->cacheBusting) {
76+
$this->queryCache()->flush($this->getTable());
77+
}
78+
79+
return parent::delete();
80+
}
81+
82+
/**
83+
* Enables cache busting.
84+
*
85+
* @return void
86+
*/
87+
public function bust()
88+
{
89+
$this->cacheBusting = true;
90+
}
91+
92+
/**
93+
* Disables cache busting.
94+
*
95+
* @return void
96+
*/
97+
public function dontBust()
98+
{
99+
$this->cacheBusting = false;
100+
}
101+
102+
/**
103+
* Returns the status of cache busting.
104+
*
105+
* @return bool
106+
*/
107+
public function isBusting()
108+
{
109+
return $this->cacheBusting;
110+
}
111+
}

src/QueryCache.php

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
<?php
2+
3+
namespace SimpleSoftwareIO\Cache;
4+
5+
use Illuminate\Cache\TaggableStore;
6+
use Illuminate\Database\Eloquent\Collection;
7+
use Illuminate\Support\Facades\Cache;
8+
9+
class QueryCache
10+
{
11+
/**
12+
* The cache store to use.
13+
*
14+
* @var string
15+
*/
16+
protected $store;
17+
18+
/**
19+
* The amount of time to store the cache.
20+
*
21+
* @var int
22+
*/
23+
protected $length = 30;
24+
25+
/**
26+
* QueryCache constructor.
27+
*
28+
* @param string $store
29+
* @param int $length
30+
*/
31+
public function __construct($store, $length)
32+
{
33+
$this->store = $store;
34+
$this->length = $length;
35+
}
36+
37+
/**
38+
* Returns the status of the cache.
39+
*
40+
* @return bool
41+
*/
42+
public function enabled()
43+
{
44+
return $this->length === 0 ? false : true;
45+
}
46+
47+
/**
48+
* Sets the length of the cache.
49+
*
50+
* @param int $minutes
51+
*/
52+
public function length($minutes)
53+
{
54+
$this->length = $minutes;
55+
}
56+
57+
/**
58+
* Enables caching on the model.
59+
*
60+
* @param int $minutes
61+
*/
62+
public function enable($minutes = 30)
63+
{
64+
$this->length($minutes);
65+
}
66+
67+
/**
68+
* Disables the cache on the model.
69+
*/
70+
public function disable()
71+
{
72+
$this->length = 0;
73+
}
74+
75+
/**
76+
* Gets the model results.
77+
*
78+
* @param QueryCacheBuilder $builder
79+
* @param array $columns
80+
* @return Collection
81+
*/
82+
public function get(QueryCacheBuilder $builder, $columns = ['*'])
83+
{
84+
if (! $this->enabled()) return $this->performQuery($builder, $columns);
85+
86+
$key = $this->generateKey($builder, $columns);
87+
88+
$cache = $this->getCache($builder);
89+
90+
return $cache->remember($key, $this->length, function () use ($builder, $columns) {
91+
return $this->performQuery($builder, $columns);
92+
});
93+
}
94+
95+
/**
96+
* Gets a Cache instance
97+
*
98+
* @return Cache
99+
*/
100+
protected function getCache(QueryCacheBuilder $builder)
101+
{
102+
return $this->isTaggable() ? Cache::store($this->store)->tags($this->getTag($builder)) : Cache::store($this->store);
103+
}
104+
105+
/**
106+
* Determines if the cache store support tagging.
107+
*
108+
* @return bool
109+
*/
110+
protected function isTaggable()
111+
{
112+
return Cache::getStore() instanceof TaggableStore;
113+
}
114+
115+
/**
116+
* Performs the query on the model.
117+
*
118+
* @param QueryCacheBuilder $builder
119+
* @param array $columns
120+
* @return mixed
121+
*/
122+
protected function performQuery(QueryCacheBuilder $builder, $columns = ['*'])
123+
{
124+
return call_user_func([$builder, 'parent::get'], $columns);
125+
}
126+
127+
/**
128+
* Generates the cache key.
129+
*
130+
* @param QueryCacheBuilder $builder
131+
* @param array $columns
132+
* @return string
133+
*/
134+
protected function generateKey(QueryCacheBuilder $builder, array $columns)
135+
{
136+
$sql = $builder->select($columns)->toSql();
137+
$whereClause = serialize($builder->getBindings());
138+
139+
return sha1($sql.$whereClause);
140+
}
141+
142+
/**
143+
* Returns the tag to tag a cache.
144+
*
145+
* @param QueryCacheBuilder $builder
146+
* @return string
147+
*/
148+
protected function getTag(QueryCacheBuilder $builder)
149+
{
150+
return $builder->from;
151+
}
152+
153+
/**
154+
* Flushes the cache for a model.
155+
*
156+
* @param $tag
157+
* @return mixed
158+
*/
159+
public function flush($tag)
160+
{
161+
if ($this->isTaggable()) return Cache::tags($tag)->flush();
162+
163+
return Cache::flush();
164+
}
165+
}

0 commit comments

Comments
 (0)