Skip to content

Commit 33c995e

Browse files
committed
Implement lazy-loading for belongs-to relationships
1 parent 11e3401 commit 33c995e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+364
-903
lines changed

src/CacheKey.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ protected function getIdColumn(string $idColumn) : string
5454

5555
protected function getLimitClause() : string
5656
{
57-
if (! $this->query->limit) {
57+
if (! property_exists($this->query, "limit")
58+
|| ! $this->query->limit
59+
) {
5860
return "";
5961
}
6062

@@ -74,7 +76,9 @@ protected function getModelSlug() : string
7476

7577
protected function getOffsetClause() : string
7678
{
77-
if (! $this->query->offset) {
79+
if (! property_exists($this->query, "offset")
80+
|| ! $this->query->offset
81+
) {
7882
return "";
7983
}
8084

@@ -83,6 +87,12 @@ protected function getOffsetClause() : string
8387

8488
protected function getOrderByClauses() : string
8589
{
90+
if (! property_exists($this->query, "orders")
91+
|| ! $this->query->orders
92+
) {
93+
return "";
94+
}
95+
8696
$orders = collect($this->query->orders);
8797

8898
return $orders
@@ -100,12 +110,15 @@ protected function getQueryColumns(array $columns) : string
100110
{
101111
if (($columns === ["*"]
102112
|| $columns === [])
103-
&& ! $this->query->columns
113+
&& (! property_exists($this->query, "columns")
114+
|| ! $this->query->columns)
104115
) {
105116
return "";
106117
}
107118

108-
if ($this->query->columns) {
119+
if (property_exists($this->query, "columns")
120+
&& $this->query->columns
121+
) {
109122
return "_" . implode("_", $this->query->columns);
110123
}
111124

@@ -302,7 +315,9 @@ protected function getWheres(array $wheres) : Collection
302315
{
303316
$wheres = collect($wheres);
304317

305-
if ($wheres->isEmpty()) {
318+
if ($wheres->isEmpty()
319+
&& property_exists($this->query, "wheres")
320+
) {
306321
$wheres = collect($this->query->wheres);
307322
}
308323

src/CachedBelongsToMany.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php namespace GeneaLabs\LaravelModelCaching;
2+
3+
use Fico7489\Laravel\Pivot\Traits\FiresPivotEventsTrait;
4+
use GeneaLabs\LaravelModelCaching\Traits\Buildable;
5+
use GeneaLabs\LaravelModelCaching\Traits\BuilderCaching;
6+
use GeneaLabs\LaravelModelCaching\Traits\Caching;
7+
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
8+
9+
class CachedBelongsToMany extends BelongsToMany
10+
{
11+
use Buildable;
12+
use BuilderCaching;
13+
use Caching;
14+
use FiresPivotEventsTrait;
15+
}

src/CachedBuilder.php

Lines changed: 2 additions & 301 deletions
Original file line numberDiff line numberDiff line change
@@ -1,312 +1,13 @@
11
<?php namespace GeneaLabs\LaravelModelCaching;
22

33
use GeneaLabs\LaravelModelCaching\Traits\BuilderCaching;
4+
use GeneaLabs\LaravelModelCaching\Traits\Buildable;
45
use GeneaLabs\LaravelModelCaching\Traits\Caching;
56
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
6-
use Illuminate\Support\Collection;
77

8-
/**
9-
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
10-
*/
118
class CachedBuilder extends EloquentBuilder
129
{
10+
use Buildable;
1311
use BuilderCaching;
1412
use Caching;
15-
16-
public function avg($column)
17-
{
18-
if (! $this->isCachable()) {
19-
return parent::avg($column);
20-
}
21-
22-
$cacheKey = $this->makeCacheKey(["*"], null, "-avg_{$column}");
23-
24-
return $this->cachedValue(func_get_args(), $cacheKey);
25-
}
26-
27-
public function count($columns = "*")
28-
{
29-
if (! $this->isCachable()) {
30-
return parent::count($columns);
31-
}
32-
33-
$cacheKey = $this->makeCacheKey([$columns], null, "-count");
34-
35-
return $this->cachedValue(func_get_args(), $cacheKey);
36-
}
37-
38-
public function decrement($column, $amount = 1, array $extra = [])
39-
{
40-
$this->cache($this->makeCacheTags())
41-
->flush();
42-
43-
return parent::decrement($column, $amount, $extra);
44-
}
45-
46-
public function delete()
47-
{
48-
$this->cache($this->makeCacheTags())
49-
->flush();
50-
51-
return parent::delete();
52-
}
53-
54-
/**
55-
* @SuppressWarnings(PHPMD.ShortVariable)
56-
*/
57-
public function find($id, $columns = ["*"])
58-
{
59-
if (! $this->isCachable()) {
60-
return parent::find($id, $columns);
61-
}
62-
63-
$idKey = collect($id)
64-
->implode('_');
65-
$preStr = is_array($id)
66-
? 'find_list'
67-
: 'find';
68-
$cacheKey = $this->makeCacheKey($columns, null, "-{$preStr}_{$idKey}");
69-
70-
return $this->cachedValue(func_get_args(), $cacheKey);
71-
}
72-
73-
public function first($columns = ["*"])
74-
{
75-
if (! $this->isCachable()) {
76-
return parent::first($columns);
77-
}
78-
79-
if (! is_array($columns)) {
80-
$columns = [$columns];
81-
}
82-
83-
$cacheKey = $this->makeCacheKey($columns, null, "-first");
84-
85-
return $this->cachedValue(func_get_args(), $cacheKey);
86-
}
87-
88-
public function forceDelete()
89-
{
90-
$this->cache($this->makeCacheTags())
91-
->flush();
92-
93-
return parent::forceDelete();
94-
}
95-
96-
public function get($columns = ["*"])
97-
{
98-
if (! $this->isCachable()) {
99-
return parent::get($columns);
100-
}
101-
102-
$cacheKey = $this->makeCacheKey($columns);
103-
104-
return $this->cachedValue(func_get_args(), $cacheKey);
105-
}
106-
107-
public function increment($column, $amount = 1, array $extra = [])
108-
{
109-
$this->cache($this->makeCacheTags())
110-
->flush();
111-
112-
return parent::increment($column, $amount, $extra);
113-
}
114-
115-
public function inRandomOrder($seed = '')
116-
{
117-
$this->isCachable = false;
118-
119-
return parent::inRandomOrder($seed);
120-
}
121-
122-
public function insert(array $values)
123-
{
124-
$this->checkCooldownAndFlushAfterPersisting($this->model);
125-
126-
return parent::insert($values);
127-
}
128-
129-
public function max($column)
130-
{
131-
if (! $this->isCachable()) {
132-
return parent::max($column);
133-
}
134-
135-
$cacheKey = $this->makeCacheKey(["*"], null, "-max_{$column}");
136-
137-
return $this->cachedValue(func_get_args(), $cacheKey);
138-
}
139-
140-
public function min($column)
141-
{
142-
if (! $this->isCachable()) {
143-
return parent::min($column);
144-
}
145-
146-
$cacheKey = $this->makeCacheKey(["*"], null, "-min_{$column}");
147-
148-
return $this->cachedValue(func_get_args(), $cacheKey);
149-
}
150-
151-
public function paginate(
152-
$perPage = null,
153-
$columns = ["*"],
154-
$pageName = "page",
155-
$page = null
156-
) {
157-
if (! $this->isCachable()) {
158-
return parent::paginate($perPage, $columns, $pageName, $page);
159-
}
160-
161-
$page = app('request')->input($pageName)
162-
?: $page
163-
?: 1;
164-
165-
if (is_array($page)) {
166-
$page = $this->recursiveImplodeWithKey($page);
167-
}
168-
$cacheKey = $this->makeCacheKey($columns, null, "-paginate_by_{$perPage}_{$pageName}_{$page}");
169-
170-
return $this->cachedValue(func_get_args(), $cacheKey);
171-
}
172-
173-
public function getRelation($name)
174-
{
175-
$relation = parent::getRelation($name);
176-
177-
if (! $this->isCachable()
178-
&& is_a($relation->getQuery(), self::class)
179-
) {
180-
$relation->getQuery()->disableModelCaching();
181-
}
182-
183-
return $relation;
184-
}
185-
186-
protected function recursiveImplodeWithKey(array $items, string $glue = "_") : string
187-
{
188-
$result = "";
189-
190-
foreach ($items as $key => $value) {
191-
if (is_array($value)) {
192-
$result .= $key . $glue . $this->recursiveImplodeWithKey($value, $glue);
193-
194-
continue;
195-
}
196-
197-
$result .= $glue . $key . $glue . $value;
198-
}
199-
200-
return $result;
201-
}
202-
203-
public function pluck($column, $key = null)
204-
{
205-
if (! $this->isCachable()) {
206-
return parent::pluck($column, $key);
207-
}
208-
209-
$keyDifferentiator = "-pluck_{$column}" . ($key ? "_{$key}" : "");
210-
$cacheKey = $this->makeCacheKey([$column], null, $keyDifferentiator);
211-
212-
return $this->cachedValue(func_get_args(), $cacheKey);
213-
}
214-
215-
public function sum($column)
216-
{
217-
if (! $this->isCachable()) {
218-
return parent::sum($column);
219-
}
220-
221-
$cacheKey = $this->makeCacheKey(["*"], null, "-sum_{$column}");
222-
223-
return $this->cachedValue(func_get_args(), $cacheKey);
224-
}
225-
226-
public function update(array $values)
227-
{
228-
$this->checkCooldownAndFlushAfterPersisting($this->model);
229-
230-
return parent::update($values);
231-
}
232-
233-
public function value($column)
234-
{
235-
if (! $this->isCachable()) {
236-
return parent::value($column);
237-
}
238-
239-
$cacheKey = $this->makeCacheKey(["*"], null, "-value_{$column}");
240-
241-
return $this->cachedValue(func_get_args(), $cacheKey);
242-
}
243-
244-
public function cachedValue(array $arguments, string $cacheKey)
245-
{
246-
$method = debug_backtrace()[1]['function'];
247-
$cacheTags = $this->makeCacheTags();
248-
$hashedCacheKey = sha1($cacheKey);
249-
$result = $this->retrieveCachedValue(
250-
$arguments,
251-
$cacheKey,
252-
$cacheTags,
253-
$hashedCacheKey,
254-
$method
255-
);
256-
257-
return $this->preventHashCollision(
258-
$result,
259-
$arguments,
260-
$cacheKey,
261-
$cacheTags,
262-
$hashedCacheKey,
263-
$method
264-
);
265-
}
266-
267-
protected function preventHashCollision(
268-
array $result,
269-
array $arguments,
270-
string $cacheKey,
271-
array $cacheTags,
272-
string $hashedCacheKey,
273-
string $method
274-
) {
275-
if ($result["key"] === $cacheKey) {
276-
return $result["value"];
277-
}
278-
279-
$this->cache()
280-
->tags($cacheTags)
281-
->forget($hashedCacheKey);
282-
283-
return $this->retrieveCachedValue(
284-
$arguments,
285-
$cacheKey,
286-
$cacheTags,
287-
$hashedCacheKey,
288-
$method
289-
);
290-
}
291-
292-
protected function retrieveCachedValue(
293-
array $arguments,
294-
string $cacheKey,
295-
array $cacheTags,
296-
string $hashedCacheKey,
297-
string $method
298-
) {
299-
$this->checkCooldownAndRemoveIfExpired($this->model);
300-
301-
return $this->cache($cacheTags)
302-
->rememberForever(
303-
$hashedCacheKey,
304-
function () use ($arguments, $cacheKey, $method) {
305-
return [
306-
"key" => $cacheKey,
307-
"value" => parent::{$method}(...$arguments),
308-
];
309-
}
310-
);
311-
}
31213
}

0 commit comments

Comments
 (0)