Tinkerwell - The PHP Scratchpad

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.

image
Tinkerwell

Enjoy coding and debugging in an editor designed for fast feedback and quick iterations. It's like a shell for your application – but with multi-line editing, code completion, and more.

Visit Tinkerwell
Bacancy logo

Bacancy

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

Bacancy
Tinkerwell logo

Tinkerwell

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

Tinkerwell
Get expert guidance in a few days with a Laravel code review logo

Get expert guidance in a few days with a Laravel code review

Expert code review! Get clear, practical feedback from two Laravel devs with 10+ years of experience helping teams build better apps.

Get expert guidance in a few days with a Laravel code review
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
Harpoon: Next generation time tracking and invoicing logo

Harpoon: Next generation time tracking and invoicing

The next generation time-tracking and billing software that helps your agency plan and forecast a profitable future.

Harpoon: Next generation time tracking and invoicing
Lucky Media logo

Lucky Media

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

Lucky Media
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

The latest

View all →
Generate Secure, Memorable Passphrases in PHP with PHP Passphrase image

Generate Secure, Memorable Passphrases in PHP with PHP Passphrase

Read article
FrankenPHP v1.11.2 Released With 30% Faster CGO, 40% Faster GC, and Security Patches image

FrankenPHP v1.11.2 Released With 30% Faster CGO, 40% Faster GC, and Security Patches

Read article
Capture Web Page Screenshots in Laravel with Spatie's Laravel Screenshot image

Capture Web Page Screenshots in Laravel with Spatie's Laravel Screenshot

Read article
Nimbus: An In-Browser API Testing Playground for Laravel image

Nimbus: An In-Browser API Testing Playground for Laravel

Read article
Laravel 12.51.0 Adds afterSending Callbacks, Validator whenFails, and MySQL Timeout image

Laravel 12.51.0 Adds afterSending Callbacks, Validator whenFails, and MySQL Timeout

Read article
Handling Large Datasets with Pagination and Cursors in Laravel MongoDB image

Handling Large Datasets with Pagination and Cursors in Laravel MongoDB

Read article