Я ищу эффективный способ загрузки настроек / конфигурации из базы данных с помощью Laravel 5. Настройки состоят из key
а также value
столбец, класс модели в основном выглядит так:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $table = 'settings';
protected $fillable = ['key', 'value'];
protected $primaryKey = 'key';
}
Сначала я сделал простую вспомогательную функцию, которая делает эту работу. Проблема в том, что это приведет к нескольким вызовам на страницу запроса. Который становится медленным.
/**
* 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'
В попытке улучшить это я создал собственный класс под названием Setting
в пределах App\Classes
каталог (а также создал для него Фасад):
<?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');
А теперь мой вопрос: это лучший способ решить эту проблему? Теперь я кеширую все настройки, когда класс создается. А затем получить значения настроек из кеша после этого.
Я начинаю понимать шаблон репозитория в L5, но я еще не там. Я думал, что это будет излишним в этом случае. Я хотел бы услышать, имеет ли смысл мой подход.
ИМХО, это немного перегружено. Вы можете сделать то же самое с помощью вспомогательного подхода:
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];
}
Менее громоздко. Нет петель. Максимум 1 БД за запрос. Максимум 1 попадание в кэш за запрос.
Вот обновленный ответ от Laravel 5.5.
Во-первых, создайте миграцию для вашего settings
Таблица:
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('key');
$table->text('value')->nullable();
$table->timestamps();
});
Затем создайте Setting
модель:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
protected $fillable = ['key', 'value'];
}
Сейчас в AppServiceProvider
Добавьте следующее к вашему boot()
метод:
if (Schema::hasTable('settings')) {
foreach (Setting::all() as $setting) {
Config::set('settings.'.$setting->key, $setting->value);
}
}
Это создаст config('settings.*')
для каждого параметра в вашей базе данных, где *
это ключ.
Например, вставьте / создайте следующий параметр:
Setting::create([
'key' => 'example',
'value' => 'Hello World',
]);
Теперь вы можете получить доступ config('settings.example')
, который даст вам Hello World
,
Обновление настроек так же просто, как и:
Setting::where('key', 'example')->update([
'value' => 'My New Value',
]);
ОП привел меня на путь развития этого пакет, который сохраняет значения пары ключей в таблицу настроек и использует кеш для сокращения запросов к БД. Если вы ищете свое собственное решение, не стесняйтесь взглянуть на мой код.
Вот как я решил это в Laravel 5.4. У меня есть таблица базы данных под названием configurations
и создал модель для этого под названием Configuration
, configurations
иметь key
а также value
как вы упомянули. Конечно, вы можете изменить это на Settings
если ты хочешь.
В AppServiceProvider
boot()
добавлять:
// cache configuration
Cache::forever('configuration', Configuration::all());
Создайте вспомогательную функцию (я поместил это в App \ Http \ helpers.php, который находится в моей автозагрузке композитора):
function configuration($key)
{
return Cache::get('configuration')->where('key', $key)->first()->value;
}
Затем вы можете получить доступ к значению в любом месте, используя configuration('key_name')
и т.п.