Installation
composer require nnjeim/persist
No additional configuration is required—just publish the facade or use dependency injection.
First Use Case Cache an API response for 5 minutes:
use Nnjeim\Persist\Facades\Persist;
$data = Persist::setCacheTag('api_data')->setCacheKey('users')->rememberCache(5 * 60, $apiResponse);
Key Files to Review
vendor/nnjeim/persist/src/Persist.php (Facade methods)vendor/nnjeim/persist/src/PersistHelper.php (Core logic)// Cache for 1 hour (TTL: 3600)
$data = Persist::setCacheTag('api')->setCacheKey('products')->rememberCache(3600, $apiData);
// Check if cached data exists
if (Persist::setCacheTag('api')->setCacheKey('products')->hasCacheKey()) {
$cachedData = Persist::getCacheKey();
}
// Set a tag (e.g., for invalidating all 'countries' cache)
Persist::setCacheTag('countries')->setCacheKey('index')->rememberCacheForever($data);
// Invalidate all keys with the 'countries' tag
Cache::tags('countries')->flush();
use Nnjeim\Persist\PersistHelper;
class CountryService {
public function __construct(private PersistHelper $persist) {}
public function fetchCountries() {
if ($this->persist->setCacheTag('countries')->setCacheKey('index')->hasCacheKey()) {
return $this->persist->getCacheKey();
}
// Fetch and cache logic...
}
}
// Fluent interface for readability
$response = Persist::setCacheTag('users')
->setCacheKey('active')
->rememberCache(300, $users)
->getCacheKey();
use Nnjeim\Fetch\Facades\Fetch;
use Nnjeim\Respond\Facades\Respond;
$response = Fetch::get('https://api.example.com/data');
if ($response->success) {
Persist::setCacheTag('api')->setCacheKey('data')->rememberCache(60, $response->data);
return Respond::toJson()->setData(Persist::getCacheKey())->withSuccess();
}
Cache Tag Mismatch
cacheTag before calling hasCacheKey() or getCacheKey() will silently fail or return stale data.setCacheTag() before other methods.TTL Misinterpretation
rememberCacheForever() does not mean "indefinite"—it uses Laravel’s default cache TTL (often 0, which may not persist).rememberCache($seconds) with a large value (e.g., 31536000 for 1 year) or configure Redis’s ttl explicitly.No Automatic Tag Invalidation
Cache::tags('countries')->flush();
Facade vs. Helper Confusion
Persist::...) and helper ($persist->...) are identical in functionality. Prefer dependency injection for testability.Check Redis Directly
redis-cli keys "*" # List all keys (use with caution in production)
redis-cli get "laravel:tags:countries:index"
Log Cache Operations
Add a debug method to the helper:
// In PersistHelper.php
public function debug(): string {
return "Tag: {$this->cacheTag}, Key: {$this->cacheKey}";
}
Handle Cache Misses Gracefully
$data = Persist::setCacheTag('api')->setCacheKey('data')->getCacheKey();
if (is_null($data)) {
$data = $this->fetchFreshData();
Persist::rememberCache(3600, $data);
}
Custom Cache Store
Override the default Redis store by binding a custom Illuminate\Contracts\Cache\Store in config/cache.php.
Add Serialization Logic
Extend PersistHelper to handle non-serializable data:
public function rememberCache($seconds, $data) {
$serialized = serialize($data); // Custom logic
return parent::rememberCache($seconds, $serialized);
}
Event-Based Invalidation Use Laravel events to flush tags:
// In a service provider
event(new CountryUpdated());
Event::listen(CountryUpdated::class, function () {
Cache::tags('countries')->flush();
});
Environment-Specific TTLs
Override TTLs in .env:
CACHE_TTL_DEFAULT=300 # 5 minutes
CACHE_TTL_API=3600 # 1 hour
Then modify PersistHelper to read these values.
api) for related keys.rememberCacheForever Sparingly: Redis may still evict keys under memory pressure.gzip before caching:
$compressed = gzcompress(serialize($data));
Persist::rememberCache(3600, $compressed);
How can I help you explore Laravel packages today?