lunzai/laravel-cache-dependency
Composer 安装命令:
composer require lunzai/laravel-cache-dependency
包简介
Dependency-based caching for Laravel with tag and database dependencies inspired by Yii2
README 文档
README
A dependency-based caching system for Laravel inspired by Yii2. Features tag dependencies with O(1) invalidation and database dependencies for automatic cache freshness.
Why This Package?
Laravel's built-in cache tags have fundamental limitations:
- Retrieval requires exact tag match — You must provide the exact same tags used when caching
- Limited driver support — Only works with Redis and Memcached
- No database dependencies — No automatic invalidation when data changes
This package solves all three problems.
Features
- Tag Dependencies: Tags stored as metadata, retrieval without tags, O(1) invalidation via version counters
- Database Dependencies: Automatic cache invalidation when query results change
- Universal Driver Support: Works with all Laravel cache drivers (file, array, database, Redis, Memcached)
- Cache Interoperability: Works seamlessly with Laravel's Cache facade
- Configurable Behavior: Fail-open or fail-closed when database queries fail
Installation
composer require lunzai/laravel-cache-dependency
Optionally publish the config:
php artisan vendor:publish --tag="cache-dependency-config"
Requirements
- PHP 8.2+
- Laravel 11+
Quick Start
use Lunzai\CacheDependency\Facades\CacheDependency; // Cache with tags CacheDependency::tags(['users', 'permissions']) ->put('user.1.permissions', $permissions, 3600); // Retrieve WITHOUT tags $permissions = CacheDependency::get('user.1.permissions'); // Invalidate — O(1) operation CacheDependency::invalidateTags('users');
Tag Dependencies
How It Works
Tags are stored as metadata with the cached entry. A version counter is maintained for each tag. When you invalidate a tag, the counter increments. On retrieval, cached entries check if their stored tag versions match current versions. If any tag version has increased, the cache is stale.
This is an O(1) operation — no iteration over cached items needed.
Usage
// Cache with tags CacheDependency::tags(['user.123', 'rbac']) ->put('user.123.permissions', $permissions, 3600); // Cache with multiple tags CacheDependency::tags(['user.123', 'role.5', 'rbac']) ->remember('user.123.permissions', 3600, function () { return $this->calculatePermissions(123); }); // Retrieve WITHOUT specifying tags $permissions = CacheDependency::get('user.123.permissions'); // Also works with standard Cache facade $permissions = Cache::get('user.123.permissions'); // Invalidate all caches with 'rbac' tag (O(1) operation) CacheDependency::invalidateTags('rbac'); // Invalidate multiple tags at once CacheDependency::invalidateTags(['user.123', 'role.5']); // Store indefinitely with tags CacheDependency::tags('config')->forever('app.settings', $settings);
Database Dependencies
How It Works
When caching, you provide a SQL query. The query result is stored as a "baseline". On retrieval, the query is re-executed and compared to the baseline. If they differ, the cache is stale.
Usage
// Simple DB dependency CacheDependency::db('SELECT MAX(updated_at) FROM roles') ->remember('all.roles', 3600, fn() => Role::all()); // DB dependency with parameters CacheDependency::db( 'SELECT MAX(updated_at) FROM role_user WHERE user_id = ?', [$userId] )->remember("user.{$userId}.roles", 3600, fn() => $user->roles); // Using named connection CacheDependency::db('SELECT COUNT(*) FROM audit_logs') ->connection('audit') ->put('audit.count', $count, 3600);
Failure Handling
When a database query fails during cache retrieval:
- Fail Closed (default): Treat as cache miss, fetch fresh data
- Fail Open: Return cached value (prioritize availability)
Configure in config/cache-dependency.php:
'db' => [ 'fail_open' => false, // Default: fail closed ],
Combined Dependencies
You can combine tags and database dependencies:
// Cache is invalidated if: // - Any tag is invalidated, OR // - DB query result changes CacheDependency::tags(['rbac', 'permissions']) ->db('SELECT MAX(updated_at) FROM permissions') ->remember('all.permissions', 3600, fn() => Permission::all());
Tag Design Patterns
Since the package uses explicit tagging (no wildcards), proper tag design is essential:
RBAC / Permission System
// Caching user permissions CacheDependency::tags([ "user.{$userId}.permissions", // Specific cache "user.{$userId}", // All caches for this user 'user.permissions', // All user permission caches 'rbac', // All RBAC-related caches ])->remember("user.{$userId}.permissions", 3600, fn() => $this->calculatePermissions($userId)); // Invalidation scenarios: CacheDependency::invalidateTags("user.{$userId}"); // User's roles changed CacheDependency::invalidateTags('user.permissions'); // Permission logic changed CacheDependency::invalidateTags('rbac'); // Clear all RBAC caches
E-commerce / Product Catalog
// Product cache CacheDependency::tags([ "product.{$productId}", "category.{$categoryId}.products", "vendor.{$vendorId}.products", 'products', ])->remember("product.{$productId}", 3600, fn() => Product::find($productId)); // Invalidation: CacheDependency::invalidateTags("product.{$productId}"); // Product updated CacheDependency::invalidateTags("category.{$categoryId}.products"); // Category products changed
Multi-tenant Application
// Tenant-scoped cache CacheDependency::tags([ "tenant.{$tenantId}", "tenant.{$tenantId}.settings", ])->remember("tenant.{$tenantId}.config", 3600, fn() => $tenant->settings); // Invalidation: CacheDependency::invalidateTags("tenant.{$tenantId}"); // Clear all tenant caches
Tag Naming Conventions
| Pattern | Use Case | Example |
|---|---|---|
entity.{id} |
All caches for a specific entity | user.123, product.456 |
entity.{id}.aspect |
Specific aspect of an entity | user.123.permissions |
entity.aspect |
All entities' aspect caches | user.permissions |
domain |
Domain-wide caches | rbac, products, settings |
parent.{id}.children |
Parent-child relationships | category.5.products |
Configuration
Publish the configuration file:
php artisan vendor:publish --tag="cache-dependency-config"
Available options:
return [ // Cache store to use (null = default) 'store' => env('CACHE_DEPENDENCY_STORE'), // Prefix for internal cache keys (tag versions) 'prefix' => env('CACHE_DEPENDENCY_PREFIX', 'cdep'), // Tag version TTL (should be longer than longest cache TTL) 'tag_version_ttl' => env('CACHE_DEPENDENCY_TAG_TTL', 86400 * 30), // 30 days 'db' => [ // Default database connection (null = default) 'connection' => env('CACHE_DEPENDENCY_DB_CONNECTION'), // Query timeout in seconds 'timeout' => env('CACHE_DEPENDENCY_DB_TIMEOUT', 5), // Behavior when DB query fails: // - false: Return null (cache miss) - fail closed // - true: Return cached value (fail open) 'fail_open' => env('CACHE_DEPENDENCY_FAIL_OPEN', false), ], ];
API Reference
CacheDependency Facade
// Create pending dependency with tags CacheDependency::tags(array|string $tags): PendingDependency // Create pending dependency with DB query CacheDependency::db(string $sql, array $params = []): PendingDependency // Retrieve from cache CacheDependency::get(string $key, mixed $default = null): mixed // Store in cache (without dependencies) CacheDependency::put(string $key, mixed $value, ?int $ttl = null): bool // Remember pattern CacheDependency::remember(string $key, ?int $ttl, Closure $callback): mixed // Invalidate tags (O(1)) CacheDependency::invalidateTags(array|string $tags): void // Get tag version CacheDependency::getTagVersion(string $tag): int // Check existence (checks staleness) CacheDependency::has(string $key): bool // Remove from cache CacheDependency::forget(string $key): bool // Retrieve and delete CacheDependency::pull(string $key, mixed $default = null): mixed // Get multiple CacheDependency::many(array $keys): array // Clear all CacheDependency::flush(): bool // Use different store CacheDependency::store(?string $name = null): CacheDependencyManager
PendingDependency Methods
// Add tags (chainable) ->tags(array|string $tags): self // Set DB dependency (chainable) ->db(string $sql, array $params = []): self // Set DB connection (chainable) ->connection(string $connection): self // Store with dependencies ->put(string $key, mixed $value, ?int $ttl = null): bool // Remember with dependencies ->remember(string $key, ?int $ttl, Closure $callback): mixed // Store forever with dependencies ->forever(string $key, mixed $value): bool // Store multiple with dependencies ->putMany(array $values, ?int $ttl = null): bool
Testing
composer test
Credits
- HL (Lunzai)
- Inspired by Yii2's Cache Dependencies
License
The MIT License (MIT). Please see License File for more information.
lunzai/laravel-cache-dependency 适用场景与选型建议
lunzai/laravel-cache-dependency 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 11 月 26 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「dependency」 「cache」 「tags」 「laravel」 「invalidation」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 lunzai/laravel-cache-dependency 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 lunzai/laravel-cache-dependency 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 lunzai/laravel-cache-dependency 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
repository php library
A powerfull cacher based on laravels file cache driver
Phalcon PHP Meta tags service
A fast and intuitive dependency injection container.
A tool for scraping URL resources (oEmbed, OpenGraph, Twitter cards, JSON-LD)
The tag extension for the yii framework
统计信息
- 总下载量: 2
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 18
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-26