JasonK JasonK -3 years ago 170
PHP Question

Laravel load settings from database

I'm looking for an efficient way to load settings/configuration from the database with Laravel 5. Settings consist of a

key
and
value
column, the model class basically looks like this:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Setting extends Model
{
protected $table = 'settings';
protected $fillable = ['key', 'value'];
protected $primaryKey = 'key';
}


At first I made a simple helper function which does the job. The problem is, this would lead to multiple calls per page request. Which is getting slow.

/**
* Get the value for the given setting from the database.
*
* @param string $key
* @return string
*/
function setting($key)
{
$setting = Setting::whereKey($key)->firstOrFail();

return $setting->value;
}

// $foo = setting('foo'); returns 'bar'


In an attempt to improve this I creating a custom class called
Setting
within the
App\Classes
directory (and also created a Facade for it):

<?php

namespace App\Classes;

use Cache;

class Setting {

/**
* The array of settings
*
* @var array $settings
*/
protected $settings = [];

/**
* Instantiate the class.
*/
public function __construct()
{
$this->loadSettings();
}

/**
* Pull the settings from the database and cache them.
*
* @return void;
*/
protected function loadSettings()
{
$settings = Cache::remember('settings', 24*60, function() {
return \App\Setting::all()->toArray();
});

$this->settings = array_pluck($settings, 'value', 'key');
}

/**
* Get all settings.
*
* @return array;
*/
public function all()
{
return $this->settings;
}

/**
* Get a setting value by it's key.
* An array of keys can be given to retrieve multiple key-value pair's.
*
* @param string|array $key;
* @return string|array;
*/
public function get($key)
{
if( is_array($key) ) {
$keys = [];

foreach($key as $k) {
$keys[$k] = $this->settings[$k];
}

return $keys;
}

return $this->settings[$key];
}

}

// $foo = Setting::get('foo');


And now for my question: is this the best way to tackle this problem? I'm now caching all the settings when the class gets constructed. And then retrieve setting values from the cache after that.

I'm beginning to understand the Repository pattern in L5, but I'm not there yet. I thought that would be overkill in this case. I would love to hear if my approach makes any sence.

Answer Source

IMHO it's a bit over engineered. You can do the same with the helper approach:

function settings($key)
{
    static $settings;

    if(is_null($settings))
    {
        $settings = Cache::remember('settings', 24*60, function() {
            return array_pluck(App\Setting::all()->toArray(), 'value', 'key');
        });
    }

    return (is_array($key)) ? array_only($settings, $key) : $settings[$key];
}

Less cumbersome. No loops. Max 1 DB hit per request. Max 1 Cache hit per request.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download