Global Application Settings

Published on by

In applications it is often useful to have a way to store some global settings. These settings are not related to a specific model, such as a user, but to the system as a whole. You can achieve this with Eloquent, of course, but I never felt that was the right approach given you are saving non-relational data in a relational system. I found Spatie’s Valuestore package to be the perfect fit for creating a settings repository for an application.

The package will take your settings and store them as a JSON file on the local filesystem. Let’s use the example of having a banner notification at the top of your application. The banner notification is visible on every page and an admin can update the text it contains.

To get started you will want to install the package.

composer require spatie/valuestore

Now you can create a Valuestore by specifying the path on disk you would like the settings to be read from, and written to. I want my settings file to be at storage/app/settings.json, so in my controller I will instantiate the Valuestore with the static make($path) method and put some values into it.

public function update(Request $request)
{
$settings = Valuestore::make(storage_path('app/settings.json'));
 
$settings->put('banner_notification', $request->banner_notification);
 
return redirect()->back()->with(['notice' => 'Settings updated']);
}

As you can see in this snippet we are adding the request input banner_notification to the Valuestore. Under the hood the Valustore package is JSON encoding the values and storing them on the filesystem in our settings.json. The package will manage this file for us, so if it doesn’t exist it will create it, and if we remove all the values it will delete the file to cleanup after itself.

The API shares many of the same methods as Laravel’s cache repository, so it should feel familiar to work with.

You are now able to access these settings in other places of your app. To do so you will need to instantiate the Valuestore with the same path we specified previously.

// The controller...
 
public function __invoke()
{
$settings = Valuestore::make(storage_path('app/settings.json'));
 
return view('homepage', ['settings' => $settings]);
}
 
// The view...
 
@if($settings->has('banner_notification'))
<div class="banner-notification">
{{ $settings->get('banner_notification') }}
</div>
@endif

The Valuestore is a really nice way to store some loose values that don’t need to be persisted to the database. No migrations, no models, just a JSON file containing your settings. The perfect fit for some basic key / value pairs. Just make sure you put your settings file in a location that is not publicly accessible.

The package also has a bunch of other really handy methods for working with your persisted data that you should checkout.

Although that is all you need to get started, I’ve also found the following tips handy when working with a Valuestore.

Binding to the container

In the previous example you can see that we had to create the Valuestore a few times and we are re-writing the instantiation logic in a few places, so instead why don’t we bind our settings to the container so we can have the instantiation logic specified in one place. This will also give us the ability to inject the Valuestore into our controllers.

First we will create our own Settings class that extends the Valuestore.

<?php
 
namespace App;
 
use Spatie\Valuestore\Valuestore;
 
class Settings extends Valuestore
{
//
}

Next we will want to bind an instance of Settings to the container as a singleton within a Service Provider.

// AppServiceProvider...
 
public function register()
{
$this->app->singleton(Settings::class, function () {
return Settings::make(storage_path('app/settings.json'));
});
}

Now we can inject our settings into a controller with Dependency Injection.

public function update(Request $request, Settings $settings)
{
$settings->put('banner_notification', $request->banner_notification);
 
return redirect()->back()->with(['notice' => 'Settings updated']);
}

Global helper

I find adding a global settings() helper also very useful when you want to access the settings in your views. Although you could achieve this with view composers or by passing through the controller as previously shown, I find the global helper is a simpler approach.

// helpers.php
 
function settings($key = null, $default = null) {
if ($key === null) {
return app(App\Settings::class);
}
 
return app(App\Settings::class)->get($key, $default);
}

In your views you can now retrieve settings via the global helper. This is especially handy when a setting, such as the banner notification, is needed on every single page.

// The view...
 
<div class="banner-notification">
 
{{ settings()->get('banner_notification') }}
 
{{-- or --}}
 
{{ settings('banner_notification') }}
 
</div>

I really like the simplicity this package introduces to enable you to store some loose values. I’ve always felt storing this kind of data in the database with some sort of key / value pair setup was never quite right. If you ever need some globally available application settings, I definitely recommend checking out Spatie’s Valuestore package. Thanks Spatie!

timacdonald photo

Developing engaging and performant web applications with a focus on TDD. Specialising in PHP / Laravel projects. ❤️ building for the web.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
No Compromises

Join the Mastering Laravel community to level up your skills and get trusted advice

Visit No Compromises

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy

Lucky Media

Bespoke software solutions built for your business. We ♥ Laravel

Lucky Media

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce

LaraJobs

The official Laravel job board

LaraJobs

Larafast: Laravel SaaS Starter Kit

Larafast is a Laravel SaaS Starter Kit with ready-to-go features for Payments, Auth, Admin, Blog, SEO, and beautiful themes. Available with Vue and Livewire stacks.

Larafast: Laravel SaaS Starter Kit

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector

The latest

View all →

Backpack turns 8 years old, celebrates with 40% discount

Read article

Create a DateTime from a Timestamp With this New Method Coming to PHP 8.4

Read article

Neovim Plugin to for Navigating Laravel and Livewire Components

Read article

Laravel Herd v1.7 is out with updates to the dump UI

Read article

Share Error Package for Laravel's New Exception Page

Read article

Sentry and Laravel announce a new partnership

Read article