diff --git a/.travis.yml b/.travis.yml index 2ff3f83..8cf2700 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,18 +3,18 @@ language: php php: - 7.0 - 7.1 + - 7.2 before_script: - travis_retry composer self-update - travis_retry composer install --no-interaction --prefer-source --dev script: - - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml + - mkdir -p ./build/logs + - ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml -after_script: - - php vendor/bin/coveralls - - wget https://scrutinizer-ci.com/ocular.phar - - php ocular.phar code-coverage:upload --format=php-clover ./build/logs/clover.xml +after_success: + - travis_retry php vendor/bin/php-coveralls -v notifications: webhooks: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b157c2..4867625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.2.13] - 28 Dec 2017 +### Added +- ability to define custom cache store in `.env` file. + ## [0.2.12] - 14 Dec 2017 ### Added - chainable method to disable caching of queries. diff --git a/README.md b/README.md index b15302f..23dd405 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,22 @@ relationships. This package is the attempt to address those requirements. - PHP >= 7.0.0 - Laravel 5.5 +## Installation +``` +composer require genealabs/laravel-model-caching +``` + +## Configuration +### Optional Custom Cache Store +If you would like to use a different cache store than the default one used by +your Laravel application, you may do so by setting the `MODEL_CACHE_STORE` +environment variable in your `.env` file to the name of a cache store configured +in `config/cache.php` (you can define any custom cache store base on your +specific needs there). For example: +``` +MODEL_CACHE_STORE=redis +``` + ## Usage For best performance a taggable cache provider is recommended (redis, memcached). While this is optional, using a non-taggable cache provider will @@ -56,7 +72,7 @@ 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. -### Disabling Caching of Queries +### Optional Disabling Caching of Queries **Recommendation: add this to all your seeder queries to avoid pulling in cached information when reseeding multiple times.** You can disable a given query by using `disableCache()` in the query chain, and diff --git a/composer.json b/composer.json index a11f451..7a49316 100644 --- a/composer.json +++ b/composer.json @@ -9,17 +9,18 @@ } ], "require": { - "php": ">=7.0.0", "illuminate/cache": "5.5.*", - "illuminate/database": "5.5.*" + "illuminate/database": "5.5.*", + "php": ">=7.0.0" }, "require-dev": { + "codedungeon/phpunit-result-printer": "^0.4.4", "fzaninotto/faker": "~1.4", "laravel/laravel": "5.5.*", "mockery/mockery": "0.9.*", "phpmd/phpmd": "^2.6", "phpunit/phpunit": "5.7.*", - "satooshi/php-coveralls" : "*", + "php-coveralls/php-coveralls" : "*", "sebastian/phpcpd": "*" }, "autoload": { @@ -34,5 +35,12 @@ "psr-4": { "GeneaLabs\\LaravelModelCaching\\Tests\\": "tests/" } + }, + "extra": { + "laravel": { + "providers": [ + "GeneaLabs\\LaravelModelCaching\\Providers\\Service" + ] + } } } diff --git a/config/laravel-model-caching.php b/config/laravel-model-caching.php new file mode 100644 index 0000000..cc75105 --- /dev/null +++ b/config/laravel-model-caching.php @@ -0,0 +1,5 @@ + env('MODEL_CACHE_STORE'), +]; diff --git a/phpunit.xml b/phpunit.xml index c3ae6e6..2be4735 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,14 +1,16 @@ - diff --git a/src/CachedBuilder.php b/src/CachedBuilder.php index a2fbeaa..a541895 100644 --- a/src/CachedBuilder.php +++ b/src/CachedBuilder.php @@ -10,8 +10,6 @@ class CachedBuilder extends EloquentBuilder { use Cachable; - protected $isCachable = true; - public function avg($column) { if (! $this->isCachable) { @@ -56,13 +54,6 @@ public function delete() return parent::delete(); } - public function disableCache() - { - $this->isCachable = false; - - return $this; - } - /** * @SuppressWarnings(PHPMD.ShortVariable) */ @@ -155,16 +146,4 @@ public function sum($column) return parent::sum($column); }); } - - protected function makeCacheKey(array $columns = ['*'], $idColumn = null) : string - { - return (new CacheKey($this->eagerLoad, $this->model, $this->query)) - ->make($columns, $idColumn); - } - - protected function makeCacheTags() : array - { - return (new CacheTags($this->eagerLoad, $this->model)) - ->make(); - } } diff --git a/src/CachedModel.php b/src/CachedModel.php index c911d7f..790c45b 100644 --- a/src/CachedModel.php +++ b/src/CachedModel.php @@ -1,6 +1,7 @@ getStore(), TaggableStore::class)) { - array_push($tags, str_slug(get_called_class())); - $cache = $cache->tags($tags); - } - - return $cache; - } - - public function disableCache() : self - { - session(['genealabs-laravel-model-caching-is-disabled' => true]); - - return $this; - } - - public function flushCache(array $tags = []) - { - $this->cache($tags)->flush(); - } - public static function all($columns = ['*']) { $class = get_called_class(); diff --git a/src/Providers/Service.php b/src/Providers/Service.php new file mode 100644 index 0000000..64afdbb --- /dev/null +++ b/src/Providers/Service.php @@ -0,0 +1,14 @@ +mergeConfigFrom($configPath, 'laravel-model-caching'); + } +} diff --git a/src/Traits/Cachable.php b/src/Traits/Cachable.php index 6f34d30..08d4119 100644 --- a/src/Traits/Cachable.php +++ b/src/Traits/Cachable.php @@ -1,17 +1,55 @@ store(config('laravel-model-caching.store')); + } + if (is_subclass_of($cache->getStore(), TaggableStore::class)) { + if (is_a($this, CachedModel::class)) { + array_push($tags, str_slug(get_called_class())); + } + $cache = $cache->tags($tags); } return $cache; } + + public function disableCache() + { + session(['genealabs-laravel-model-caching-is-disabled' => true]); + $this->isCachable = false; + + return $this; + } + + public function flushCache(array $tags = []) + { + $this->cache($tags)->flush(); + } + + protected function makeCacheKey(array $columns = ['*'], $idColumn = null) : string + { + return (new CacheKey($this->eagerLoad, $this->model, $this->query)) + ->make($columns, $idColumn); + } + + protected function makeCacheTags() : array + { + return (new CacheTags($this->eagerLoad, $this->model)) + ->make(); + } } diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php index 20300b6..9c275d3 100644 --- a/tests/CreatesApplication.php +++ b/tests/CreatesApplication.php @@ -1,5 +1,6 @@ afterResolving('migrator', function ($migrator) { $migrator->path(__DIR__ . '/database/migrations'); }); + $app->register(LaravelModelCachingService::class); return $app; } diff --git a/tests/Unit/CachedModelTest.php b/tests/Unit/CachedModelTest.php index db34ec4..eb48379 100644 --- a/tests/Unit/CachedModelTest.php +++ b/tests/Unit/CachedModelTest.php @@ -62,9 +62,6 @@ public function testAllModelResultsCreatesCache() $this->assertEmpty($liveResults->diffAssoc($cachedResults)); } - /** - * @group test - **/ public function testScopeDisablesCaching() { $key = 'genealabslaravelmodelcachingtestsfixturesauthor'; diff --git a/tests/Unit/Traits/CachableTest.php b/tests/Unit/Traits/CachableTest.php new file mode 100644 index 0000000..f1218b7 --- /dev/null +++ b/tests/Unit/Traits/CachableTest.php @@ -0,0 +1,72 @@ +flush(); + $publishers = factory(Publisher::class, 10)->create(); + factory(Author::class, 10)->create() + ->each(function ($author) use ($publishers) { + factory(Book::class, random_int(2, 10))->make() + ->each(function ($book) use ($author, $publishers) { + $book->author()->associate($author); + $book->publisher()->associate($publishers[rand(0, 9)]); + $book->save(); + }); + factory(Profile::class)->make([ + 'author_id' => $author->id, + ]); + }); + + $bookIds = (new Book)->all()->pluck('id'); + factory(Store::class, 10)->create() + ->each(function ($store) use ($bookIds) { + $store->books()->sync(rand($bookIds->min(), $bookIds->max())); + }); + cache()->flush(); + } + + public function testSpecifyingAlternateCacheDriver() + { + $configCacheStores = config('cache.stores'); + $configCacheStores['customCache'] = ['driver' => 'array']; + config(['cache.stores' => $configCacheStores]); + config(['laravel-model-caching.store' => 'customCache']); + $key = 'genealabslaravelmodelcachingtestsfixturesauthor'; + $tags = ['genealabslaravelmodelcachingtestsfixturesauthor']; + + $authors = (new Author) + ->all(); + $defaultcacheResults = cache() + ->tags($tags) + ->get($key); + $customCacheResults = cache() + ->store('customCache') + ->tags($tags) + ->get($key); + $liveResults = (new UncachedAuthor) + ->all(); + + $this->assertEquals($customCacheResults, $authors); + $this->assertNull($defaultcacheResults); + $this->assertEmpty($liveResults->diffAssoc($customCacheResults)); + } +}