APCu Cache
APCu (Alternative PHP Cache - User) provides fast in-memory caching for PHP applications.
APCu Cache Methods
| Method | Description |
|---|---|
get($key) | Get cached value |
put($key, $value, $ttl) | Store value with TTL |
forget($key) | Remove cached value |
remember($key, $callback, $ttl) | Get or compute and cache |
has($key) | Check if key exists |
flush() | Clear all cache |
increment($key) | Increment numeric value |
decrement($key) | Decrement numeric value |
Basic Usage
use Miko\Cache\ApcuCache;
$cache = new ApcuCache('myapp_'); // Prefix for keys
// Store value (TTL in seconds)
$cache->put('user:1', $userData, 3600); // 1 hour
// Get value
$user = $cache->get('user:1');
// Get with default
$user = $cache->get('user:1', null);
// Check existence
if ($cache->has('user:1')) {
// Key exists
}
// Remove
$cache->forget('user:1');
// Clear all
$cache->flush();
Remember Pattern
Get from cache or compute and store:
// If cached, return cached value
// If not, execute callback, cache result, and return
$user = $cache->remember('user:1', function() {
return User::find(1);
}, 3600);
// With complex computation
$stats = $cache->remember('dashboard:stats', function() {
return [
'users' => User::count(),
'orders' => Order::count(),
'revenue' => Order::sum('TotalAmount')
];
}, 300); // 5 minutes
Increment / Decrement
// Initialize counter
$cache->put('visitors', 0, 86400);
// Increment
$cache->increment('visitors');
$cache->increment('visitors', 5); // Increment by 5
// Decrement
$cache->decrement('stock:123');
$cache->decrement('stock:123', 2); // Decrement by 2
// Get current value
$count = $cache->get('visitors');
Tags Support
Group related cache entries:
// Store with tags
$cache->putWithTags('user:1', $userData, 3600, ['users', 'user_1']);
$cache->putWithTags('user:1:orders', $orders, 3600, ['users', 'user_1', 'orders']);
// Invalidate by tag
$cache->forgetByTag('user_1'); // Removes all user_1 related cache
// Invalidate all users
$cache->forgetByTag('users');
Cache Statistics
$stats = $cache->getStats();
// Returns:
// [
// 'hits' => 15000,
// 'misses' => 500,
// 'hit_rate' => 96.77,
// 'memory_used' => 52428800,
// 'memory_available' => 134217728,
// 'entries' => 1250
// ]
echo "Hit rate: " . $stats['hit_rate'] . "%";
echo "Memory: " . round($stats['memory_used'] / 1024 / 1024, 2) . " MB";
Practical Examples
User Session Cache
class SessionCache
{
private ApcuCache $cache;
public function __construct()
{
$this->cache = new ApcuCache('session_');
}
public function getUser(int $userId): ?User
{
return $this->cache->remember("user:$userId", function() use ($userId) {
return User::with('roles', 'permissions')->find($userId);
}, 1800); // 30 minutes
}
public function invalidateUser(int $userId): void
{
$this->cache->forget("user:$userId");
}
}
API Rate Limiting
class RateLimiter
{
private ApcuCache $cache;
public function __construct()
{
$this->cache = new ApcuCache('rate_');
}
public function attempt(string $key, int $maxAttempts, int $decaySeconds): bool
{
$attempts = $this->cache->get($key, 0);
if ($attempts >= $maxAttempts) {
return false;
}
if ($attempts === 0) {
$this->cache->put($key, 1, $decaySeconds);
} else {
$this->cache->increment($key);
}
return true;
}
public function remaining(string $key, int $maxAttempts): int
{
return max(0, $maxAttempts - $this->cache->get($key, 0));
}
}
// Usage
$limiter = new RateLimiter();
$ip = $_SERVER['REMOTE_ADDR'];
if (!$limiter->attempt("api:$ip", 100, 60)) {
http_response_code(429);
die('Rate limit exceeded');
}
Configuration Cache
class ConfigCache
{
private ApcuCache $cache;
public function __construct()
{
$this->cache = new ApcuCache('config_');
}
public function get(string $key, $default = null)
{
return $this->cache->remember("config:$key", function() use ($key, $default) {
$setting = Setting::where('Key', $key)->first();
return $setting ? $setting->Value : $default;
}, 3600);
}
public function set(string $key, $value): void
{
Setting::updateOrCreate(['Key' => $key], ['Value' => $value]);
$this->cache->forget("config:$key");
}
public function clearAll(): void
{
$this->cache->flush();
}
}
Requirements
APCu must be installed and enabled:
; php.ini
extension=apcu
apc.enabled=1
apc.shm_size=128M
apc.ttl=7200
Check if available:
if (!extension_loaded('apcu') || !apcu_enabled()) {
throw new Exception('APCu is not available');
}
Best Practices
| Practice | Description |
|---|---|
| Use prefixes | Avoid key collisions between apps |
| Set appropriate TTL | Balance freshness vs performance |
| Use tags | Easier cache invalidation |
| Monitor memory | Don't exceed available memory |
| Handle misses | Always have fallback for cache misses |