Global Application Settings

Published on by

Global Application Settings image

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.

Laravel Forge logo

Laravel Forge

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

Laravel Forge
Tinkerwell logo

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 logo

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 logo

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 logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

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 logo

LaraJobs

The official Laravel job board

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant 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
Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate logo

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate

Build your SaaS application in hours. Out-of-the-box multi-tenancy and seamless Stripe integration. Supports subscriptions and one-time purchases, allowing you to focus on building and creating without repetitive setup tasks.

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate
Rector logo

Rector

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

Rector
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
Asymmetric Property Visibility in PHP 8.4 image

Asymmetric Property Visibility in PHP 8.4

Read article
Access Laravel Pulse Data as a JSON API image

Access Laravel Pulse Data as a JSON API

Read article
Laravel Forge adds Statamic Integration image

Laravel Forge adds Statamic Integration

Read article
Transform Data into Type-safe DTOs with this PHP Package image

Transform Data into Type-safe DTOs with this PHP Package

Read article
PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell image

PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell

Read article
Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3 image

Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3

Read article