PHP code example of aftandilmmd / laravel-cacheable

1. Go to this page and download the library: Download aftandilmmd/laravel-cacheable library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

aftandilmmd / laravel-cacheable example snippets


#[Cacheable(key: 'user.{id}', ttl: 3600, tags: ['users'])]
public function find(int $id): User
{
    return User::findOrFail($id); // only runs on cache miss
}

// app/Repositories/UserRepository.php

use Aftandilmmd\Cacheable\Attributes\Cacheable;

class UserRepository
{
    // Cache a single user for 1 hour.
    #[Cacheable(key: 'user.{id}', ttl: 3600, tags: ['users'])]
    public function find(int $id): ?User
    {
        return User::find($id);
    }

    // Cache the active user list for 10 minutes.
    #[Cacheable(key: 'users.active', ttl: 600, tags: ['users'])]
    public function allActive(): Collection
    {
        return User::where('active', true)->get();
    }

    // On update: forget this user's entry and flush the list.
    #[Cacheable(forget: ['user.{id}'], forgetTags: ['users'])]
    public function update(int $id, array $data): bool
    {
        return (bool) User::where('id', $id)->update($data);
    }

    // On delete: same invalidation.
    #[Cacheable(forget: ['user.{id}'], forgetTags: ['users'])]
    public function delete(int $id): bool
    {
        return (bool) User::destroy($id);
    }
}

// config/cacheable.php
'auto_proxy' => [
    App\Repositories\UserRepository::class,
],

// app/Http/Controllers/UserController.php

class UserController extends Controller
{
    public function __construct(private UserRepository $users) {}

    public function show(int $id): JsonResponse
    {
        return response()->json($this->users->find($id)); // served from cache
    }

    public function update(int $id, Request $request): JsonResponse
    {
        $this->users->update($id, $request->validated()); // updates DB + clears cache
        return response()->json($this->users->find($id)); // already fresh
    }
}

// config/cacheable.php
'auto_proxy' => [
    App\Services\UserService::class,
],

// app/Http/Controllers/UserController.php

class UserController extends Controller
{
    public function __construct(private UserService $service) {}

    public function show(int $id): JsonResponse
    {
        return response()->json($this->service->find($id)); // cached
    }
}

use Aftandilmmd\Cacheable\Facades\Cacheable;

$service = Cacheable::proxy(new UserService());
$user = $service->find(42); // cached

// app/Services/UserService.php

use Aftandilmmd\Cacheable\Concerns\HasCacheableMethods;

class UserService
{
    use HasCacheableMethods;

    #[Cacheable(key: 'user.{id}', ttl: 3600)]
    public function find(int $id): User { ... }

    #[Cacheable(key: 'users.active', ttl: 600)]
    public static function active(): Collection { ... }
}

$service->cached('find', [42]); // instance method
$service->cached('active');     // static method — same call

use Aftandilmmd\Cacheable\Support\CacheableProxy;

$proxy = CacheableProxy::wrapClass(UserService::class);
$proxy->active(); // calls UserService::active() through the cache layer

#[Cacheable(ttl: 3600)]
public function all(): Collection { ... }

#[Cacheable(key: 'user.{id}.posts', ttl: 600)]
public function posts(int $id): Collection { ... }

#[Cacheable(key: 'order.{order.id}.items', ttl: 600)]
public function items(Order $order): Collection { ... }

#[Cacheable(ttl: null, tags: ['static'])]
public function countries(): array { ... }

#[Cacheable(ttl: 3600, tags: ['users'])]
public function find(int $id): User { ... }

#[Cacheable(ttl: 3600, when: 'shouldCache')]
public function expensive(string $type): array { ... }

public function shouldCache(string $type): bool
{
    return $type !== 'realtime';
}

#[Cacheable(key: 'search.{q}', ttl: 300, excludeParams: ['request', 'logger'])]
public function search(string $q, Request $request, LoggerInterface $logger): array { ... }

#[Cacheable(forget: ['user.{id}'], forgetTags: ['users'])]
public function update(int $id, array $data): bool
{
    return User::find($id)->update($data);
}

use Aftandilmmd\Cacheable\Facades\Cacheable;

Cacheable::forget(UserService::class, 'find', [42]);
Cacheable::flushTags(['users']);

// config/cacheable.php
'version' => env('CACHEABLE_VERSION', 'v2'), // was v1

#[Cacheable(key: 'user.{id}', ttl: 3600, version: 'v2')]

#[Cacheable(key: 'report.{date}', ttl: 3600, lock: true, lockWait: 15)]
public function heavyReport(string $date): array { ... }

#[Cacheable(ttl: 3600, jitter: 300)] // effective TTL: 3600–3900 seconds
public function popular(): array { ... }

#[Cacheable(key: 'dashboard', ttl: 600, refreshAhead: 0.2)]
public function dashboardStats(): array { ... }

// config/cacheable.php
'swr' => [
    'async'            => true,
    'queue_connection' => 'redis',
    'queue_name'       => 'cache',
],

// app/Providers/AppServiceProvider.php

use Aftandilmmd\Cacheable\Events\CacheHit;
use Aftandilmmd\Cacheable\Events\CacheMissed;
use Aftandilmmd\Cacheable\Events\CacheWritten;
use Aftandilmmd\Cacheable\Events\CacheForgotten;

Event::listen(CacheHit::class, function (CacheHit $event) {
    Log::debug('Cache HIT', ['key' => $event->key, 'method' => $event->method]);
});

Event::listen(CacheMissed::class, function (CacheMissed $event) {
    Log::debug('Cache MISS', ['key' => $event->key, 'method' => $event->method]);
});

Event::listen(CacheWritten::class, function (CacheWritten $event) {
    Log::debug('Cache WRITTEN', ['key' => $event->key, 'ttl' => $event->ttl]);
});

Event::listen(CacheForgotten::class, function (CacheForgotten $event) {
    Log::debug('Cache FORGOTTEN', ['keys' => $event->keys, 'tags' => $event->tags]);
});

use Aftandilmmd\Cacheable\Facades\Cacheable;

// See exactly which key would be generated for a call
$key = Cacheable::keyFor(UserService::class, 'find', [42]);
// → "cacheable:v1:App\Services\UserService:find:a1b2c3..."

// Delete the cached value and immediately re-execute the method to warm cache
Cacheable::refresh(UserService::class, 'find', [42]);

return [
    'enabled' => env('CACHEABLE_ENABLED', true),
    'store'   => env('CACHEABLE_STORE'),           // null = Laravel default
    'prefix'  => env('CACHEABLE_PREFIX', 'cacheable'),
    'version' => env('CACHEABLE_VERSION', 'v1'),
    'ttl'     => env('CACHEABLE_TTL', 3600),

    'keys' => [
        'hash_algo'  => 'xxh128',
        'serializer' => 'json',   // 'json' | 'serialize' | 'igbinary'
        'max_length' => 200,
    ],

    'stampede' => [
        'jitter'    => 0,
        'lock_wait' => 10,
    ],

    'swr' => [
        'refresh_ahead'    => 0.0,
        'async'            => false,
        'queue_connection' => env('CACHEABLE_SWR_CONNECTION'),
        'queue_name'       => env('CACHEABLE_SWR_QUEUE', 'default'),
    ],

    'storage' => [
        'cache_null'  => false,
        'cache_empty' => true,
    ],

    'events' => [
        'enabled' => true,
    ],

    'auto_proxy' => [
        // App\Services\UserService::class,
    ],
];

// app/Services/TenantAwareKeyResolver.php

use Aftandilmmd\Cacheable\Contracts\KeyResolver;

class TenantAwareKeyResolver implements KeyResolver
{
    public function __construct(private KeyResolver $inner) {}

    public function resolve(...$args): string
    {
        return tenant()->id . ':' . $this->inner->resolve(...$args);
    }
}

// app/Providers/AppServiceProvider.php

$this->app->extend(KeyResolver::class, fn ($inner) =>
    new TenantAwareKeyResolver($inner)
);

// app/Providers/AppServiceProvider.php

$this->app->singleton(ArgumentNormalizer::class, MyNormalizer::class);
bash
php artisan vendor:publish --tag=cacheable-config
bash
php artisan vendor:publish --tag=cacheable-config