diff --git a/README.md b/README.md index 8760a25..219fb14 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ relationships. This package is an attempt to address those requirements. - automatic, self-invalidating model query caching. - automatic use of cache tags for cache providers that support them (will flush entire cache for providers that don't). +- support for multitenant implementations by implementing getCachePrefix method in the Model class ## Requirements - PHP >= 7.1.3 @@ -74,6 +75,18 @@ extends `Illuminate\Foundation\Auth\User`. Overriding that would break functiona Not only that, but it probably isn't a good idea to cache the user model anyway, since you always want to pull the most up-to-date info on it. +### Multitenant support for cached models +If you need multitenant support the same model context (key and tags) needs to be cached for each tenant with it's specific values. This requires a separations of cache that is supported by implementing the getCachePrefix method in the model class. + +I would recommend to implement in your application a TenantCachable trait for your models containing the getCachePrefix method that for example returns a unique value corresponding to each tenant. +An example in the context of using the hyn/multi-tenant package can be: +```php +public function getCachePrefix() +{ + return $this->getConnectionName() . '-' . $this->getConnection()->getDatabaseName(); +} +``` + ### Optional Disabling Caching of Queries **Recommendation: add this to all your seeder queries to avoid pulling in cached information when reseeding multiple times.** diff --git a/src/CacheGlobal.php b/src/CacheGlobal.php new file mode 100644 index 0000000..a1d69cf --- /dev/null +++ b/src/CacheGlobal.php @@ -0,0 +1,26 @@ +getStore(), TaggableStore::class)) { - if (is_a($this, CachedModel::class)) { - array_push($tags, str_slug(get_called_class())); + if (is_a($this, Model::class)) { + array_push($tags, $this->makeCachePrefix(str_slug(get_called_class()))); } $cache = $cache->tags($tags); @@ -34,7 +36,8 @@ protected function cache(array $tags = []) public function disableCache() { - cache()->forever(self::$isCachableKey, true); + + CacheGlobal::disableCache(); $this->isCachable = false; @@ -50,24 +53,86 @@ public function flushCache(array $tags = []) $this->cache($tags)->flush(); } + protected function retrieveEagerLoad() + { + if (is_a($this, Model::class)) { + return []; + } + if (is_a($this, EloquentBuilder::class)) { + return $this->eagerLoad ?? []; + } + return null; + } + + protected function retrieveCacheModel() + { + if (is_a($this, Model::class)) { + return $this; + } + if (is_a($this, EloquentBuilder::class)) { + return $this->model; + } + return null; + } + + protected function retrieveCacheQuery() + { + if (is_a($this, Model::class)) { + return app(Builder::class); + } + if (is_a($this, EloquentBuilder::class)) { + return $this->query; + } + return null; + } + + protected function makeCachePrefix($elementMix) + { + $model = $this->retrieveCacheModel(); + if (!method_exists($model, "getCachePrefix")) { + return $elementMix; + } + + $result = null; + $cachePrefix = $model->getCachePrefix(); + if ($cachePrefix == null) { + return $elementMix; + } + if (is_array($elementMix)) { + $result = []; + foreach ($elementMix as $value) { + array_push($result, $cachePrefix . '-' . $value); + } + return $result; + } else { + $result = $cachePrefix . '-' . $elementMix; + } + return $result; + } + protected function makeCacheKey( array $columns = ['*'], $idColumn = null, string $keyDifferentiator = '' ) : string { - $eagerLoad = $this->eagerLoad ?? []; - $model = $this->model ?? $this; - $query = $this->query ?? app(Builder::class); + $eagerLoad = $this->retrieveEagerLoad(); + $model = $this->retrieveCacheModel(); + $query = $this->retrieveCacheQuery(); return (new CacheKey($eagerLoad, $model, $query)) - ->make($columns, $idColumn, $keyDifferentiator); + ->make($columns, $idColumn, $this->makeCachePrefix($keyDifferentiator)); } protected function makeCacheTags() : array { - $tags = (new CacheTags($this->eagerLoad ?? [], $this->model ?? $this)) + $eagerLoad = $this->retrieveEagerLoad(); + $model = $this->retrieveCacheModel(); + + $tags = (new CacheTags($eagerLoad, $model)) ->make(); + $tags = $this->makeCachePrefix($tags); + return $tags; } @@ -80,13 +145,13 @@ public static function bootCachable() public static function all($columns = ['*']) { - if (cache()->get(self::$isCachableKey)) { + if (CacheGlobal::isDisabled()) { return parent::all($columns); } $class = get_called_class(); $instance = new $class; - $tags = [str_slug(get_called_class())]; + $tags = $this->makeCachePrefix([str_slug(get_called_class())]); $key = $instance->makeCacheKey(); return $instance->cache($tags) @@ -97,8 +162,8 @@ public static function all($columns = ['*']) public function newEloquentBuilder($query) { - if (cache()->get(self::$isCachableKey)) { - cache()->forget(self::$isCachableKey); + if (CacheGlobal::isDisabled()) { + CacheGlobal::enableCache(); return new EloquentBuilder($query); }