Skip to content

Rudnev/laravel-settings

Repository files navigation

Laravel Settings

Build Status StyleCI License: MIT Laravel Octane Compatible

Persistent settings for Laravel Framework

  • Easy to Use
  • App Settings + User Settings (Scopes)
  • Events
  • Cache
  • Extendable Settings Manager
  • Laravel Octane compatible

Requirements

  • PHP 7.1 or higher
  • Laravel 5.5 or higher

Basic usage

Retrieve and store data using the global settings function:

// app settings:

settings()->set('timezone', 'UTC');
settings()->get('timezone');

// the same:

settings(['timezone' => 'UTC']);
settings('timezone');

// user settings:

settings()->scope($user)->set('lang', 'en');
settings()->scope($user)->get('lang');

You can also use the Settings facade:

Settings::set('timezone', 'UTC');
Settings::get('timezone');

And if you prefer contracts, you can use Method dependency injection:

<?php

namespace App\Http\Controllers;

use Rudnev\Settings\Contracts\RepositoryContract as Settings;

class MyController extends Controller
{
    public function index(Settings $settings)
    {
        $tz = $settings->get('timezone');
    }
}

Getting started

Installation
API
Scopes
Translation
Cache
Events
Custom store


Installation

You can install the package via composer:

composer require rudnev/laravel-settings

Publish the config file and the migration with:

php artisan vendor:publish --provider="Rudnev\Settings\ServiceProvider"

After the migration has been published you can create the settings table by running the migrations:

php artisan migrate

API

Check the value

Determine if an item exists in the settings store.

Settings::has('foo');

Get the value

Retrieve an item from the settings store by key.

Settings::get('foo');

// You can specify a default value when an property is null or not found:

Settings::get('foo', 'default'); 

Get multiple values

Retrieve multiple items from the settings store by key. Items not found in the settings store will have a null value.

Settings::get(['foo', 'bar', 'baz']);

// with default value:

Settings::get(['foo', 'bar', 'baz' => 'default']);

Get all values

Get all the settings items.

Settings::all();

Set the value

Store an item in the settings store.

Settings::set('foo', 'bar');

Set multiple values

Store multiple items in the settings store.

Settings::set([
    'foo' => 'bar', 
    'qux' => 'baz'
]);

Remove the value

Remove an item from the settings store.

Settings::forget('foo');

Remove multiple values

Remove multiple items from the settings store.

Settings::forget(['foo', 'bar']);

Remove all values

Remove all items from the settings store.

Settings::flush();

Dot Notation

You can use dot syntax to indicate the item depth:

Settings::set('products.desk', ['price' => 300, 'height' => 100]);
Settings::forget('products.desk.price');
Settings::has('products.desk.height');
Settings::get('products.desk');

Scopes

If you want to have settings for your model you can use scope method:

$user = auth()->user();

Settings::scope($user)->set('lang', 'en');

Settings::scope($user)->get('lang');

But instead, it's better to use the Rudnev\Settings\Traits\HasSettings trait, for example:

use Rudnev\Settings\Traits\HasSettings;
use Illuminate\Database\Eloquent\Model;

class User extends Model 
{
    use HasSettings;
    
    // ...
}

Now you can use settings property to set and get values:

$user = new User();
$user->settings = ['lang' => 'en'];
$user->save();

echo $user->settings['lang'];

$user->settings['timezone'] = 'UTC';
$user->save();

Also, settings method provides direct access to the settings store (but model state will not be updated):

$user->settings()->set('lang', 'en');
$user->settings()->get('lang');

// the same:

$user->settings(['lang' => 'en']);
$user->settings('lang');

To set the default settings define $settingsConfig property as array with default key:

use Rudnev\Settings\Traits\HasSettings;
use Illuminate\Database\Eloquent\Model;

class User extends Model 
{
    use HasSettings;
    
    protected $settingsConfig = [
        'default' => [
            'timezone' => 'UTC'
        ]
    ];
    
    // ...
}

And if you want specify the store from config/settings.php, use store option:

protected $settingsConfig = [
    'store' => 'database',
	
    'default' => [
        'timezone' => 'UTC'
    ]
];

In addition to the scopes for models, you can freely create scopes for your application settings, for example:

// Set
Settings::scope('my-landing-page')->set('tracking_id', 'UA-000000-2');

// Get
Settings::scope('my-landing-page')->get('tracking_id');

Translation

I suggest using the built-in laravel methods to translate any keys, names and descriptions. You can use this approach for most laravel packages, there is no need to store translations within different database tables when you can do this in one place.

For example, create a file resources/lang/en/settings.php:

<?php

return [
    'user' => [
        'language' => [
            'name' => 'Language',
            'description' => 'The site language.'    
        ],
        
        'mfa' => [
            'name' => 'MFA',
            'description' => 'Multi-factor authentication.'    
        ],
    ]
];

And get translated strings:

$user = auth()->user();
$userSettings = Settings::scope($user);

// Store locale:
$userSettings->set('language', 'en');

// Store some settings:
$userSettings->set('mfa', 'enabled');

// Retrieve locale:
$locale = $userSettings->get('language');

// Apply locale:
App::setLocale($locale);

// Print translated strings:
foreach ($userSettings->all() as $key => $value)
{
    $name = trans("settings.user.$key.name");
    $desc = trans("settings.user.$key.description");
    
    echo "$name: $value ($desc)" . PHP_EOL;
}

Cache

Cache is enabled by default, you can change this in your config/settings.php file.

To clear the cache you can run the following Artisan command:

php artisan settings:clear-cache

Note: this command does not actually delete cache entries, it only invalidates them by changing the prefix for keys. If you are using settings for models, the cache can grow quickly. For this reason, it is recommended to use drivers that support eviction policies, such as redis, or use the command php artisan cache:clear to completely clear the cache.

Events

Events are triggered if this is not disabled via config (enabled by default).

Event Description
\Rudnev\Settings\Events\PropertyWritten Fired after the value is written to the store.
\Rudnev\Settings\Events\PropertyReceived Fired after the value is retrieved from the store.
\Rudnev\Settings\Events\PropertyMissed Fired if the item not found or is not set.
\Rudnev\Settings\Events\PropertyRemoved Fired after the item is removed from the store.
\Rudnev\Settings\Events\AllSettingsReceived Fired after retrieving all items from the store.
\Rudnev\Settings\Events\AllSettingsRemoved Fired after removing all items from the store.

Custom Store

To create your own store, you must use the extend method on the SettingsManager, which is used to bind a custom driver resolver to the manager, but first you need implement the StoreContract:

use Rudnev\Settings\Contracts\StoreContract;

class MongoStore implements StoreContract {
// ...
}

After that, to register a new settings driver named "mongo", you would do the following:

Settings::extend('mongo', function($app, $storeName, $config)
{
    return Settings::repository(new MongoStore);
});

The first argument passed to the extend method is the name of the driver. This will correspond to your driver option in the config/settings.php configuration file. The second argument is a Closure that should return an Rudnev\Settings\Repository instance. The Closure will be passed an $app instance, which is an instance of Illuminate\Foundation\Application and a service container.

The call to Settings::extend could be done in the boot method of the default App\Providers\AppServiceProvider that ships with fresh Laravel applications, or you may create your own service provider to house the extension.

Finally, you can access your store as follows:

Settings::store('mongo')->get('foo');

Credits

License

The MIT License (MIT). Please see License File for more information.