DEV Community

David Chamling Rai
David Chamling Rai

Posted on

Laravel Settings Caching Done Right – With Service Layer and Auto Re-Caching

In many Laravel apps, especially admin dashboards or multi-tenant platforms, you often fetch settings like tax_percentage, facebook_link, support_email, etc., directly from the database — again and again.

This guide shows you how to:

  • Cache these settings for faster performance
  • Access them easily via a clean service
  • Automatically update the cache when settings change

Let’s keep it simple and practical — no nested arrays, no JSON decoding.


Step 1: Create the Settings Table

Schema::create('settings', function (Blueprint $table) {
    $table->id();
    $table->string('key')->unique();
    $table->text('value')->nullable();
    $table->timestamps();
});
Enter fullscreen mode Exit fullscreen mode

Sample Data

key value
tax_percentage 13
facebook_link https://fb.com/myapp
support_email support@example.com

Step 2: Build a Simple Settings Service

We’ll use a service class to manage caching and access so we don’t repeat ourselves or hardcode cache logic.

php artisan make:service SettingService
Enter fullscreen mode Exit fullscreen mode

app/Services/SettingService.php

namespace App\Services;

use Illuminate\Support\Facades\Cache;
use App\Models\Setting;

class SettingService
{
    protected static string $cacheKey = 'app_settings';

    public static function all(): array
    {
        return Cache::rememberForever(self::$cacheKey, function () {
            return Setting::all()->pluck('value', 'key')->toArray();
        });
    }

    public static function get(string $key, $default = null)
    {
        return self::all()[$key] ?? $default;
    }

    public static function recache(): void
    {
        $settings = Setting::all()->pluck('value', 'key')->toArray();
        Cache::forever(self::$cacheKey, $settings);
    }
}
Enter fullscreen mode Exit fullscreen mode

⚠️ A Note for Large-Scale Projects

In smaller to mid-sized applications, caching all settings at once is convenient and fast.

But in large projects with a high volume of settings — for example, tenant-specific or modular settings — caching the entire settings table might be unnecessary or inefficient.

👉 In such cases, consider fetching and caching individual or grouped settings using dynamic cache keys.


🧪 Step 3: Use the Service in Your App

Anywhere in your app:

use App\Services\SettingService;

$tax = SettingService::get('tax_percentage'); // "13"
$facebook = SettingService::get('facebook_link'); // "https://fb.com/myapp"

// or
$settings = SettingService::all();
$tax = $settings->tax_percentage;
$facebook = $settings->facebook_link;
Enter fullscreen mode Exit fullscreen mode

No need to touch the cache directly. It’s all handled through one clean service.


🔁 Step 4: Manual Re-caching in Controller (Not Recommended)

public function update(Request $request)
{
  // validate request
  // update setting
    Setting::updateOrCreate(
        ['key' => 'tax_percentage'],
        ['value' => $request->input('tax_percentage')]
    );

    // Manually update the cache
    \App\Services\SettingService::recache();

    return response()->json(['message' => 'Setting updated successfully.']);
}
Enter fullscreen mode Exit fullscreen mode

Problem: If you update settings in multiple places (controllers, seeders, etc.), you’ll have to remember to call recache() every time. That’s easy to forget.


Step 5: Auto Re-cache with Model Observer (Recommended)

5.1: Create the Observer

php artisan make:observer SettingObserver --model=Setting
Enter fullscreen mode Exit fullscreen mode

app/Observers/SettingObserver.php

namespace App\Observers;

use App\Models\Setting;
use App\Services\SettingService;

class SettingObserver
{
    public function saved(Setting $setting): void
    {
        SettingService::recache();
    }

    public function deleted(Setting $setting): void
    {
        SettingService::recache();
    }
}
Enter fullscreen mode Exit fullscreen mode

5.2: Register the Observer

In AppServiceProvider.php:

use App\Models\Setting;
use App\Observers\SettingObserver;

public function boot(): void
{
    Setting::observe(SettingObserver::class);
}
Enter fullscreen mode Exit fullscreen mode

✅ Now, every time a setting is created, updated, or deleted, the cache updates automatically.


✅ Final Thoughts

With this setup:

  • ✅ Settings are cached for fast access
  • ✅ Logic is centralized in a clean service
  • ✅ You never need to worry about stale cache again

Simple, scalable, and production-ready.


🎁 Bonus: Add a Global Helper

If you prefer calling setting('tax_percentage') instead of using the service class directly:

if (!function_exists('setting')) {
    function setting(string $key = null, $default = null)
    {
        return $key
            ? \App\Services\SettingService::get($key, $default)
            : \App\Services\SettingService::all();
    }
}
Enter fullscreen mode Exit fullscreen mode

Now you can use:

setting('facebook_link');
Enter fullscreen mode Exit fullscreen mode

Clean and intuitive.


🙌 Did this help you?

If you found this guide helpful, please consider:

  • Sharing it with your dev circle or community
  • 🐦 Following me for more practical Laravel and JavaScript tips
  • 💬 Commenting below if you have questions or improvements

Thanks for reading! 👋


Top comments (0)