diff --git a/README.md b/README.md
index cbed213..a5e79fb 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,27 @@ smart_cache(['products' => $products], 3600);
$products = smart_cache('products');
```
+### Using Different Cache Drivers
+
+Use different cache drivers while maintaining all SmartCache optimizations:
+
+```php
+// Use Redis with all SmartCache optimizations (compression, chunking, etc.)
+SmartCache::store('redis')->put('key', $value, 3600);
+SmartCache::store('redis')->get('key');
+
+// Use Memcached with optimizations
+SmartCache::store('memcached')->remember('users', 3600, fn() => User::all());
+
+// Use file cache with optimizations
+SmartCache::store('file')->put('config', $config, 86400);
+
+// For raw access to Laravel's cache (bypasses SmartCache optimizations)
+SmartCache::repository('redis')->put('key', $value, 3600);
+```
+
+> **Full Laravel Compatibility:** SmartCache implements Laravel's `Repository` interface, so it works seamlessly with any code that type-hints `Illuminate\Contracts\Cache\Repository`. The `store()` method returns a SmartCache instance that is also a valid Repository.
+
## 💡 Core Features (Automatic Optimization)
### 1. Intelligent Compression
diff --git a/docs/index.html b/docs/index.html
index ed277ed..bffa22a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -763,6 +763,35 @@
Familiar Laravel API
// Clear all cache
SmartCache::flush();
+ Using Different Cache Drivers
+ Use different cache drivers while maintaining all SmartCache optimizations:
+
+ // Use Redis with all SmartCache optimizations (compression, chunking, etc.)
+SmartCache::store('redis')->put('key', $value, 3600);
+SmartCache::store('redis')->get('key');
+
+// Use Memcached with optimizations
+SmartCache::store('memcached')->remember('users', 3600, fn() => User::all());
+
+// Use file cache with optimizations
+SmartCache::store('file')->put('config', $config, 86400);
+
+// Chain multiple operations on a specific store
+$redisCache = SmartCache::store('redis');
+$redisCache->put('users', $users, 3600);
+$redisCache->put('products', $products, 3600);
+
+// For raw access to Laravel's cache (bypasses SmartCache optimizations)
+SmartCache::repository('redis')->put('key', $value, 3600);
+
+
+ Note: The store() method returns a SmartCache instance, so all optimization strategies (compression, chunking, encryption, etc.) continue to work. Use repository() if you need direct access to Laravel's cache without SmartCache optimizations.
+
+
+
+ Full Laravel Compatibility: SmartCache implements Laravel's Illuminate\Contracts\Cache\Repository interface, so it works seamlessly with any code that type-hints Repository. The store() method returns a SmartCache instance that is also a valid Repository, ensuring zero breaking changes when migrating from Laravel's Cache facade.
+
+
Automatic Optimization
SmartCache automatically optimizes your data when beneficial:
@@ -1712,6 +1741,61 @@ 🔧 Basic Cache Operations
+
+
SmartCache::store() Enhanced!
+
SmartCache::store(string|null $name = null): static
+
Get a SmartCache instance for a specific cache driver. All SmartCache optimizations (compression, chunking, encryption, etc.) are preserved. The returned instance also implements Illuminate\Contracts\Cache\Repository for full Laravel compatibility.
+
+ $name (string|null) - The cache store name (redis, file, memcached, etc.)
+
+
+ Returns: static - SmartCache instance configured for the specified store (also implements Repository)
+
+
+
Examples:
+
// Use Redis with all SmartCache optimizations
+SmartCache::store('redis')->put('key', $value, 3600);
+SmartCache::store('redis')->get('key');
+
+// Use Memcached with optimizations
+SmartCache::store('memcached')->remember('users', 3600, fn() => User::all());
+
+// Chain operations on a specific store
+$redisCache = SmartCache::store('redis');
+$redisCache->put('users', $users, 3600);
+$redisCache->put('products', $products, 3600);
+
+// Works with Repository type hints
+function cacheData(\Illuminate\Contracts\Cache\Repository $cache) {
+ $cache->put('key', 'value', 3600);
+}
+cacheData(SmartCache::store('redis')); // ✅ Works!
+
+
+
+
+
SmartCache::repository() New!
+
SmartCache::repository(string|null $name = null): \Illuminate\Contracts\Cache\Repository
+
Get direct access to Laravel's underlying cache repository. This bypasses all SmartCache optimizations.
+
+ $name (string|null) - The cache store name (redis, file, memcached, etc.)
+
+
+ Returns: Repository - Laravel's native cache repository
+
+
+
Examples:
+
// Direct access to Redis cache (no SmartCache optimizations)
+SmartCache::repository('redis')->put('key', $value, 3600);
+
+// Direct access to default cache store
+SmartCache::repository()->get('key');
+
+
+ Note: Use repository() only when you need to bypass SmartCache optimizations. For normal usage, prefer store() to maintain all optimization benefits.
+
+
+
🌊 SWR Patterns (Laravel 12+)
diff --git a/src/Console/Commands/ClearCommand.php b/src/Console/Commands/ClearCommand.php
index a8e7338..861c1cf 100644
--- a/src/Console/Commands/ClearCommand.php
+++ b/src/Console/Commands/ClearCommand.php
@@ -112,8 +112,7 @@ protected function clearAllKeys(SmartCache $cache): int
protected function clearOrphanedKeys(SmartCache $cache): int
{
- $repository = $cache->store();
- $store = $repository->getStore();
+ $store = $cache->getStore();
$cleared = 0;
$managedKeys = $cache->getManagedKeys();
@@ -122,7 +121,7 @@ protected function clearOrphanedKeys(SmartCache $cache): int
foreach ($allKeys as $key) {
if (!\in_array($key, $managedKeys, true) && !$this->isSmartCacheInternalKey($key)) {
- if ($repository->forget($key)) {
+ if ($cache->store()->forget($key)) {
$cleared++;
$this->line("Cleared key: {$key}");
}
diff --git a/src/Console/Commands/StatusCommand.php b/src/Console/Commands/StatusCommand.php
index 36824fa..09ce510 100644
--- a/src/Console/Commands/StatusCommand.php
+++ b/src/Console/Commands/StatusCommand.php
@@ -123,8 +123,7 @@ protected function displayConfiguration(ConfigRepository $config): void
protected function findAllNonManagedKeys(SmartCache $cache): array
{
- $repository = $cache->store();
- $store = $repository->getStore();
+ $store = $cache->getStore();
$managedKeys = $cache->getManagedKeys();
$nonManagedKeys = [];
diff --git a/src/Contracts/SmartCache.php b/src/Contracts/SmartCache.php
index 0fbe0c0..f1610aa 100644
--- a/src/Contracts/SmartCache.php
+++ b/src/Contracts/SmartCache.php
@@ -2,84 +2,38 @@
namespace SmartCache\Contracts;
-interface SmartCache
+use Illuminate\Contracts\Cache\Repository;
+
+/**
+ * SmartCache Contract
+ *
+ * This interface extends Laravel's Repository interface to ensure full compatibility
+ * with Laravel's cache system while adding SmartCache-specific optimization features.
+ */
+interface SmartCache extends Repository
{
/**
- * Get an item from the cache.
+ * Get a SmartCache instance using a specific cache store.
*
- * @param string $key
- * @param mixed $default
- * @return mixed
- */
- public function get(string $key, mixed $default = null): mixed;
-
- /**
- * Store an item in the cache.
- *
- * @param string $key
- * @param mixed $value
- * @param \DateTimeInterface|\DateInterval|int|null $ttl
- * @return bool
- */
- public function put(string $key, mixed $value, $ttl = null): bool;
-
- /**
- * Determine if an item exists in the cache.
- *
- * @param string $key
- * @return bool
- */
- public function has(string $key): bool;
-
- /**
- * Remove an item from the cache.
- *
- * @param string $key
- * @return bool
- */
- public function forget(string $key): bool;
-
- /**
- * Store an item in the cache indefinitely.
- *
- * @param string $key
- * @param mixed $value
- * @return bool
- */
- public function forever(string $key, mixed $value): bool;
-
- /**
- * Get an item from the cache, or execute the given Closure and store the result.
- *
- * @param string $key
- * @param \DateTimeInterface|\DateInterval|int|null $ttl
- * @param \Closure $callback
- * @return mixed
- */
- public function remember(string $key, $ttl, \Closure $callback): mixed;
-
- /**
- * Get an item from the cache, or execute the given Closure and store the result forever.
+ * When called without arguments, returns the current instance.
+ * When called with a store name, returns a new SmartCache instance
+ * configured to use that store while maintaining all optimization strategies.
*
- * @param string $key
- * @param \Closure $callback
- * @return mixed
+ * @param string|null $name The cache store name (e.g., 'redis', 'file', 'memcached')
+ * @return static
*/
- public function rememberForever(string $key, \Closure $callback): mixed;
+ public function store(string|null $name = null): static;
/**
- * Get the underlying cache store.
+ * Get the underlying cache repository directly.
*
- * @return \Illuminate\Contracts\Cache\Repository
- */
- public function store(string|null $name = null): \Illuminate\Contracts\Cache\Repository;
-
- /**
- * Clear all cache keys managed by SmartCache.
+ * This provides raw access to Laravel's cache repository without SmartCache optimizations.
+ * Use this when you need direct access to the cache driver.
*
- * @return bool
+ * @param string|null $name The store name (null for current store)
+ * @return Repository
*/
- public function clear(): bool;
+ public function repository(string|null $name = null): Repository;
/**
* Get all keys managed by SmartCache.
@@ -291,14 +245,6 @@ public function many(array $keys): array;
*/
public function putMany(array $values, $ttl = null): bool;
- /**
- * Remove multiple items from the cache.
- *
- * @param array $keys
- * @return bool
- */
- public function deleteMultiple(array $keys): bool;
-
/**
* Get a memoized cache instance.
*
diff --git a/src/Facades/SmartCache.php b/src/Facades/SmartCache.php
index 8a9821d..f6f961c 100644
--- a/src/Facades/SmartCache.php
+++ b/src/Facades/SmartCache.php
@@ -16,7 +16,8 @@
* @method static mixed swr(string $key, \Closure $callback, int $ttl = 3600, int $staleTtl = 7200)
* @method static mixed stale(string $key, \Closure $callback, int $ttl = 1800, int $staleTtl = 86400)
* @method static mixed refreshAhead(string $key, \Closure $callback, int $ttl = 3600, int $refreshWindow = 600)
- * @method static \Illuminate\Contracts\Cache\Repository store(string|null $name = null)
+ * @method static \SmartCache\SmartCache store(string|null $name = null)
+ * @method static \Illuminate\Contracts\Cache\Repository repository(string|null $name = null)
* @method static bool clear()
* @method static array getManagedKeys()
* @method static static tags(string|array $tags)
@@ -35,7 +36,7 @@
* @method static array analyzePerformance()
* @method static int cleanupExpiredManagedKeys()
* @method static bool hasFeature(string $feature)
- *
+ *
* @see \SmartCache\SmartCache
*/
class SmartCache extends Facade
diff --git a/src/SmartCache.php b/src/SmartCache.php
index 5e3144a..920d909 100644
--- a/src/SmartCache.php
+++ b/src/SmartCache.php
@@ -3,6 +3,7 @@
namespace SmartCache;
use Illuminate\Contracts\Cache\Repository;
+use Illuminate\Contracts\Cache\Store;
use Illuminate\Contracts\Cache\Factory as CacheManager;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Illuminate\Support\Facades\Log;
@@ -16,7 +17,7 @@
use SmartCache\Traits\HasLocks;
use SmartCache\Traits\DispatchesCacheEvents;
-class SmartCache implements SmartCacheContract
+class SmartCache implements SmartCacheContract, Repository
{
use HasLocks, DispatchesCacheEvents;
/**
@@ -170,9 +171,9 @@ public function addStrategy(OptimizationStrategy $strategy): self
/**
* {@inheritdoc}
*/
- public function get(string $key, mixed $default = null): mixed
+ public function get($key, $default = null): mixed
{
- $key = $this->applyNamespace($key);
+ $key = $this->applyNamespace((string) $key);
$startTime = $this->enablePerformanceMonitoring ? microtime(true) : null;
$value = $this->cache->get($key, null);
@@ -212,9 +213,9 @@ protected function trackAccessFrequency(string $key): void
/**
* {@inheritdoc}
*/
- public function put(string $key, mixed $value, $ttl = null): bool
+ public function put($key, $value, $ttl = null): bool
{
- $key = $this->applyNamespace($key);
+ $key = $this->applyNamespace((string) $key);
$startTime = $this->enablePerformanceMonitoring ? microtime(true) : null;
$optimizedValue = $this->maybeOptimizeValue($value, $key, $ttl);
@@ -241,21 +242,45 @@ public function put(string $key, mixed $value, $ttl = null): bool
return $result;
}
+ /**
+ * PSR-16 alias for put().
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @return bool
+ */
+ public function set($key, $value, $ttl = null): bool
+ {
+ return $this->put($key, $value, $ttl);
+ }
+
/**
* {@inheritdoc}
*/
- public function has(string $key): bool
+ public function has($key): bool
{
- $key = $this->applyNamespace($key);
+ $key = $this->applyNamespace((string) $key);
return $this->cache->has($key);
}
+ /**
+ * PSR-16 alias for forget().
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function delete($key): bool
+ {
+ return $this->forget($key);
+ }
+
/**
* {@inheritdoc}
*/
- public function forget(string $key): bool
+ public function forget($key): bool
{
- $key = $this->applyNamespace($key);
+ $key = $this->applyNamespace((string) $key);
$value = $this->cache->get($key);
// If value is chunked, clean up all chunk keys
@@ -285,9 +310,9 @@ public function forget(string $key): bool
/**
* {@inheritdoc}
*/
- public function forever(string $key, mixed $value): bool
+ public function forever($key, $value): bool
{
- $key = $this->applyNamespace($key);
+ $key = $this->applyNamespace((string) $key);
$optimizedValue = $this->maybeOptimizeValue($value, $key, null);
// Track all keys for pattern matching and invalidation
@@ -304,45 +329,182 @@ public function forever(string $key, mixed $value): bool
/**
* {@inheritdoc}
*/
- public function remember(string $key, $ttl, \Closure $callback): mixed
+ public function remember($key, $ttl, \Closure $callback): mixed
{
if ($this->has($key)) {
return $this->get($key);
}
-
+
$value = $callback();
$this->put($key, $value, $ttl);
-
+
return $value;
}
+ /**
+ * Get an item from the cache, or execute the given Closure and store the result forever.
+ * This is an alias for rememberForever().
+ *
+ * @param string $key
+ * @param \Closure $callback
+ * @return mixed
+ */
+ public function sear($key, \Closure $callback): mixed
+ {
+ return $this->rememberForever($key, $callback);
+ }
+
/**
* {@inheritdoc}
*/
- public function rememberForever(string $key, \Closure $callback): mixed
+ public function rememberForever($key, \Closure $callback): mixed
{
if ($this->has($key)) {
return $this->get($key);
}
-
+
$value = $callback();
$this->forever($key, $value);
-
+
return $value;
}
/**
* {@inheritdoc}
*/
- public function store(string|null $name = null): Repository
+ public function store(string|null $name = null): static
+ {
+ if ($name === null) {
+ return $this;
+ }
+
+ // Create a new SmartCache instance with the specified store
+ // This preserves all optimization strategies while using a different cache driver
+ return new static(
+ $this->cacheManager->store($name),
+ $this->cacheManager,
+ $this->config,
+ $this->strategies
+ );
+ }
+
+ /**
+ * Get the underlying cache repository.
+ *
+ * This provides direct access to the Laravel cache repository without SmartCache optimizations.
+ * Use this when you need raw access to the cache driver.
+ *
+ * @param string|null $name The store name (null for current store)
+ * @return Repository
+ */
+ public function repository(string|null $name = null): Repository
{
if ($name === null) {
return $this->cache;
}
-
+
return $this->cacheManager->store($name);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getStore(): Store
+ {
+ return $this->cache->getStore();
+ }
+
+ /**
+ * Retrieve an item from the cache and delete it.
+ *
+ * @param array|string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function pull($key, $default = null): mixed
+ {
+ $value = $this->get($key, $default);
+ $this->forget($key);
+ return $value;
+ }
+
+ /**
+ * Store an item in the cache if the key does not exist.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @return bool
+ */
+ public function add($key, $value, $ttl = null): bool
+ {
+ if ($this->has($key)) {
+ return false;
+ }
+
+ return $this->put($key, $value, $ttl);
+ }
+
+ /**
+ * Increment the value of an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return int|bool
+ */
+ public function increment($key, $value = 1): int|bool
+ {
+ $key = $this->applyNamespace((string) $key);
+ return $this->cache->increment($key, $value);
+ }
+
+ /**
+ * Decrement the value of an item in the cache.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return int|bool
+ */
+ public function decrement($key, $value = 1): int|bool
+ {
+ $key = $this->applyNamespace((string) $key);
+ return $this->cache->decrement($key, $value);
+ }
+
+ /**
+ * PSR-16: Obtains multiple cache items identified by their unique keys.
+ *
+ * @param iterable $keys
+ * @param mixed $default
+ * @return iterable
+ */
+ public function getMultiple($keys, $default = null): iterable
+ {
+ $results = [];
+ foreach ($keys as $key) {
+ $results[$key] = $this->get($key, $default);
+ }
+ return $results;
+ }
+
+ /**
+ * PSR-16: Persists a set of key => value pairs in the cache.
+ *
+ * @param iterable $values
+ * @param \DateTimeInterface|\DateInterval|int|null $ttl
+ * @return bool
+ */
+ public function setMultiple($values, $ttl = null): bool
+ {
+ $success = true;
+ foreach ($values as $key => $value) {
+ if (!$this->put($key, $value, $ttl)) {
+ $success = false;
+ }
+ }
+ return $success;
+ }
+
/**
* {@inheritdoc}
*/
@@ -1785,10 +1947,10 @@ public function putMany(array $values, $ttl = null): bool
/**
* Remove multiple items from the cache.
*
- * @param array $keys
+ * @param iterable $keys
* @return bool
*/
- public function deleteMultiple(array $keys): bool
+ public function deleteMultiple($keys): bool
{
$success = true;
diff --git a/tests/Unit/Console/ClearCommandTest.php b/tests/Unit/Console/ClearCommandTest.php
index e992580..7ba739f 100644
--- a/tests/Unit/Console/ClearCommandTest.php
+++ b/tests/Unit/Console/ClearCommandTest.php
@@ -63,17 +63,12 @@ public function test_clear_command_with_no_managed_keys_and_force()
->twice() // Called once for display, once in clearOrphanedKeys
->andReturn([]);
- // Mock the store to return a cache repository that will simulate an unsupported driver
- $mockRepository = Mockery::mock(\Illuminate\Contracts\Cache\Repository::class);
+ // Mock getStore to return a store that will simulate an unsupported driver
$mockStore = Mockery::mock(\stdClass::class); // Use stdClass to simulate unsupported driver
-
- $mockRepository->shouldReceive('getStore')
+
+ $this->mockSmartCache->shouldReceive('getStore')
->once()
->andReturn($mockStore);
-
- $this->mockSmartCache->shouldReceive('store')
- ->once()
- ->andReturn($mockRepository);
// Inject the mock into the command
$this->command->setLaravel($this->app);
@@ -302,17 +297,17 @@ public function test_clear_specific_key_not_managed_but_exists_with_force()
->once()
->with($existingKey)
->andReturn(true);
-
- // Mock the store() method to return a cache repository
- $mockStore = Mockery::mock(\Illuminate\Contracts\Cache\Repository::class);
- $mockStore->shouldReceive('forget')
+
+ // Mock the store() method to return a SmartCache instance for non-managed key clearing
+ $mockStoreInstance = Mockery::mock(SmartCache::class);
+ $mockStoreInstance->shouldReceive('forget')
->once()
->with($existingKey)
->andReturn(true);
-
+
$this->mockSmartCache->shouldReceive('store')
->once()
- ->andReturn($mockStore);
+ ->andReturn($mockStoreInstance);
// Inject the mock into the command
$this->command->setLaravel($this->app);
diff --git a/tests/Unit/Console/StatusCommandTest.php b/tests/Unit/Console/StatusCommandTest.php
index e511c48..1c3de63 100644
--- a/tests/Unit/Console/StatusCommandTest.php
+++ b/tests/Unit/Console/StatusCommandTest.php
@@ -300,19 +300,14 @@ public function test_status_command_with_force_option_no_orphaned_keys()
->with('smart-cache')
->once()
->andReturn($this->getDefaultSmartCacheConfig());
-
- // Mock the store() method to return a cache repository
- $mockRepository = Mockery::mock(\Illuminate\Contracts\Cache\Repository::class);
+
+ // Mock getStore() to return a cache store
$mockStore = Mockery::mock(\Illuminate\Cache\ArrayStore::class);
-
- $mockRepository->shouldReceive('getStore')
+
+ $this->mockSmartCache->shouldReceive('getStore')
->once()
->andReturn($mockStore);
-
- $this->mockSmartCache->shouldReceive('store')
- ->once()
- ->andReturn($mockRepository);
-
+
// Mock has() calls to check if managed keys exist
$this->mockSmartCache->shouldReceive('has')
->with('key1')
@@ -354,19 +349,14 @@ public function test_status_command_with_force_option_finds_missing_managed_keys
->with('smart-cache')
->once()
->andReturn($this->getDefaultSmartCacheConfig());
-
- // Mock the store() method to return a cache repository
- $mockRepository = Mockery::mock(\Illuminate\Contracts\Cache\Repository::class);
+
+ // Mock getStore() to return a cache store
$mockStore = Mockery::mock(\Illuminate\Cache\ArrayStore::class);
-
- $mockRepository->shouldReceive('getStore')
+
+ $this->mockSmartCache->shouldReceive('getStore')
->once()
->andReturn($mockStore);
-
- $this->mockSmartCache->shouldReceive('store')
- ->once()
- ->andReturn($mockRepository);
-
+
// Mock has() calls - one key exists, two are missing
$this->mockSmartCache->shouldReceive('has')
->with('existing-key')
diff --git a/tests/Unit/SmartCacheTest.php b/tests/Unit/SmartCacheTest.php
index 8eb1990..4d81bb6 100644
--- a/tests/Unit/SmartCacheTest.php
+++ b/tests/Unit/SmartCacheTest.php
@@ -244,15 +244,104 @@ public function test_managed_keys_tracking()
$this->assertContains($key2, $managedKeys);
}
- public function test_can_get_different_cache_stores()
+ public function test_store_returns_smart_cache_instance()
{
- // Test getting default store
+ // Test getting default store returns self
$defaultStore = $this->smartCache->store();
- $this->assertEquals($this->getCacheStore(), $defaultStore);
+ $this->assertInstanceOf(\SmartCache\SmartCache::class, $defaultStore);
+ $this->assertSame($this->smartCache, $defaultStore);
- // Test getting named store
+ // Test getting named store returns a new SmartCache instance
$arrayStore = $this->smartCache->store('array');
- $this->assertNotNull($arrayStore);
+ $this->assertInstanceOf(\SmartCache\SmartCache::class, $arrayStore);
+ $this->assertNotSame($this->smartCache, $arrayStore);
+ }
+
+ public function test_store_method_preserves_optimization_strategies()
+ {
+ // Create a SmartCache instance with compression enabled
+ $smartCache = new SmartCache(
+ $this->getCacheStore(),
+ $this->getCacheManager(),
+ $this->app['config'],
+ [new CompressionStrategy(1024, 6)]
+ );
+
+ // Get a store instance for array driver
+ $arraySmartCache = $smartCache->store('array');
+
+ // Store large data through the new store instance
+ $key = 'store-optimization-test';
+ $value = $this->createCompressibleData();
+
+ $arraySmartCache->put($key, $value);
+
+ // Verify the value is compressed in the raw cache
+ $rawCached = $this->getCacheStore('array')->get($key);
+ $this->assertValueIsCompressed($rawCached);
+
+ // Verify we can retrieve the original value
+ $retrieved = $arraySmartCache->get($key);
+ $this->assertEquals($value, $retrieved);
+ }
+
+ public function test_store_method_allows_chaining_operations()
+ {
+ // Test that store() allows chaining cache operations
+ $key = 'chained-store-key';
+ $value = 'chained-value';
+
+ // Put using chained store
+ $this->smartCache->store('array')->put($key, $value, 3600);
+
+ // Get using chained store
+ $retrieved = $this->smartCache->store('array')->get($key);
+ $this->assertEquals($value, $retrieved);
+
+ // Remember using chained store
+ $rememberValue = $this->smartCache->store('array')->remember('remember-chain-key', 3600, fn() => 'remembered');
+ $this->assertEquals('remembered', $rememberValue);
+ }
+
+ public function test_store_method_uses_correct_driver()
+ {
+ $key = 'driver-test-key';
+ $value = 'test-value';
+
+ // Store in array driver via store() method
+ $this->smartCache->store('array')->put($key, $value);
+
+ // Value should be in array store
+ $this->assertTrue($this->smartCache->store('array')->has($key));
+
+ // Value should not be in file store (different driver)
+ $this->assertFalse($this->smartCache->store('file')->has($key));
+ }
+
+ public function test_repository_method_returns_raw_cache()
+ {
+ // Test getting default repository
+ $defaultRepo = $this->smartCache->repository();
+ $this->assertInstanceOf(\Illuminate\Contracts\Cache\Repository::class, $defaultRepo);
+ $this->assertEquals($this->getCacheStore(), $defaultRepo);
+
+ // Test getting named repository
+ $arrayRepo = $this->smartCache->repository('array');
+ $this->assertInstanceOf(\Illuminate\Contracts\Cache\Repository::class, $arrayRepo);
+ }
+
+ public function test_repository_bypasses_optimization()
+ {
+ $key = 'repository-bypass-test';
+ $value = $this->createCompressibleData(); // Large, compressible data
+
+ // Store via repository (should bypass SmartCache optimization)
+ $this->smartCache->repository()->put($key, $value);
+
+ // Get raw value - should NOT be compressed since we used repository
+ $rawCached = $this->getCacheStore()->get($key);
+ $this->assertEquals($value, $rawCached);
+ $this->assertIsString($rawCached); // Not wrapped in optimization array
}
public function test_chunked_data_cleanup_on_forget()
@@ -540,6 +629,190 @@ public function test_flexible_method_with_optimization_integration()
$this->assertNull($this->smartCache->get($metaKey));
}
+ // ========================================
+ // Repository Interface Compliance Tests
+ // ========================================
+
+ public function test_smart_cache_implements_repository_interface()
+ {
+ $this->assertInstanceOf(\Illuminate\Contracts\Cache\Repository::class, $this->smartCache);
+ }
+
+ public function test_pull_retrieves_and_deletes_item()
+ {
+ $key = 'pull-test-key';
+ $value = 'pull-test-value';
+
+ $this->smartCache->put($key, $value);
+ $this->assertTrue($this->smartCache->has($key));
+
+ $pulled = $this->smartCache->pull($key);
+ $this->assertEquals($value, $pulled);
+ $this->assertFalse($this->smartCache->has($key));
+ }
+
+ public function test_pull_returns_default_when_key_missing()
+ {
+ $default = 'default-value';
+ $pulled = $this->smartCache->pull('non-existent-key', $default);
+ $this->assertEquals($default, $pulled);
+ }
+
+ public function test_add_stores_item_only_if_not_exists()
+ {
+ $key = 'add-test-key';
+
+ // Add should succeed when key doesn't exist
+ $result = $this->smartCache->add($key, 'first-value');
+ $this->assertTrue($result);
+ $this->assertEquals('first-value', $this->smartCache->get($key));
+
+ // Add should fail when key already exists
+ $result = $this->smartCache->add($key, 'second-value');
+ $this->assertFalse($result);
+ $this->assertEquals('first-value', $this->smartCache->get($key)); // Still first value
+ }
+
+ public function test_increment_increases_value()
+ {
+ $key = 'increment-test-key';
+ $this->getCacheStore()->put($key, 5);
+
+ $result = $this->smartCache->increment($key);
+ $this->assertEquals(6, $result);
+
+ $result = $this->smartCache->increment($key, 3);
+ $this->assertEquals(9, $result);
+ }
+
+ public function test_decrement_decreases_value()
+ {
+ $key = 'decrement-test-key';
+ $this->getCacheStore()->put($key, 10);
+
+ $result = $this->smartCache->decrement($key);
+ $this->assertEquals(9, $result);
+
+ $result = $this->smartCache->decrement($key, 4);
+ $this->assertEquals(5, $result);
+ }
+
+ public function test_sear_is_alias_for_remember_forever()
+ {
+ $key = 'sear-test-key';
+ $callCount = 0;
+
+ $callback = function () use (&$callCount) {
+ $callCount++;
+ return 'seared-value';
+ };
+
+ // First call should execute callback
+ $value = $this->smartCache->sear($key, $callback);
+ $this->assertEquals('seared-value', $value);
+ $this->assertEquals(1, $callCount);
+
+ // Second call should return cached value without executing callback
+ $value = $this->smartCache->sear($key, $callback);
+ $this->assertEquals('seared-value', $value);
+ $this->assertEquals(1, $callCount); // Callback should not be called again
+ }
+
+ public function test_set_is_alias_for_put()
+ {
+ $key = 'set-test-key';
+ $value = 'set-test-value';
+
+ $result = $this->smartCache->set($key, $value);
+ $this->assertTrue($result);
+ $this->assertEquals($value, $this->smartCache->get($key));
+ }
+
+ public function test_delete_is_alias_for_forget()
+ {
+ $key = 'delete-test-key';
+ $value = 'delete-test-value';
+
+ $this->smartCache->put($key, $value);
+ $this->assertTrue($this->smartCache->has($key));
+
+ $result = $this->smartCache->delete($key);
+ $this->assertTrue($result);
+ $this->assertFalse($this->smartCache->has($key));
+ }
+
+ public function test_get_store_returns_underlying_store()
+ {
+ $store = $this->smartCache->getStore();
+ $this->assertInstanceOf(\Illuminate\Contracts\Cache\Store::class, $store);
+ }
+
+ public function test_get_multiple_retrieves_multiple_items()
+ {
+ $this->smartCache->put('multi1', 'value1');
+ $this->smartCache->put('multi2', 'value2');
+ $this->smartCache->put('multi3', 'value3');
+
+ $results = $this->smartCache->getMultiple(['multi1', 'multi2', 'multi3']);
+
+ $this->assertIsIterable($results);
+ $this->assertEquals('value1', $results['multi1']);
+ $this->assertEquals('value2', $results['multi2']);
+ $this->assertEquals('value3', $results['multi3']);
+ }
+
+ public function test_get_multiple_returns_default_for_missing_keys()
+ {
+ $this->smartCache->put('existing', 'exists');
+
+ $results = $this->smartCache->getMultiple(['existing', 'missing'], 'default');
+
+ $this->assertEquals('exists', $results['existing']);
+ $this->assertEquals('default', $results['missing']);
+ }
+
+ public function test_set_multiple_stores_multiple_items()
+ {
+ $values = [
+ 'setmulti1' => 'val1',
+ 'setmulti2' => 'val2',
+ 'setmulti3' => 'val3',
+ ];
+
+ $result = $this->smartCache->setMultiple($values);
+ $this->assertTrue($result);
+
+ $this->assertEquals('val1', $this->smartCache->get('setmulti1'));
+ $this->assertEquals('val2', $this->smartCache->get('setmulti2'));
+ $this->assertEquals('val3', $this->smartCache->get('setmulti3'));
+ }
+
+ public function test_delete_multiple_removes_multiple_items()
+ {
+ $this->smartCache->put('del1', 'value1');
+ $this->smartCache->put('del2', 'value2');
+ $this->smartCache->put('del3', 'value3');
+
+ $result = $this->smartCache->deleteMultiple(['del1', 'del2']);
+ $this->assertTrue($result);
+
+ $this->assertFalse($this->smartCache->has('del1'));
+ $this->assertFalse($this->smartCache->has('del2'));
+ $this->assertTrue($this->smartCache->has('del3')); // This one was not deleted
+ }
+
+ public function test_store_returns_repository_compatible_instance()
+ {
+ $storeInstance = $this->smartCache->store('array');
+
+ // Should be both SmartCache and Repository
+ $this->assertInstanceOf(\SmartCache\SmartCache::class, $storeInstance);
+ $this->assertInstanceOf(\Illuminate\Contracts\Cache\Repository::class, $storeInstance);
+
+ // Should have getStore() method working
+ $this->assertInstanceOf(\Illuminate\Contracts\Cache\Store::class, $storeInstance->getStore());
+ }
+
protected function tearDown(): void
{
Mockery::close();