В приложениях часто нужно хранить некоторые глобальные настройки, причем эти параметры не относятся к конкретной модели, например пользователю, а к системе в целом. Конечно, вы можете сделать это через Eloquent, но я считаю, что это неправильный подход, так как вы сохраняете нереляционные данные в реляционной системе. И я нашёл для этого пакет Spatie Valuestore, который идеально подходит для хранения настроек приложения.

Пакет берет ваши настройки и сохраняет их в виде JSON файла в локальной файловой системе. Давайте рассмотрим пример с баннерным уведомлением. Оно показывается на каждой странице, и администратор может управлять его содержимым.

Для начала установим пакет:

composer require spatie/valuestore

Теперь создадим Valuestore (хранилище значений), указав путь на диске. Мой файл настроек находится в storage/app/settings.json, поэтому я создам в контроллере экземпляр Valuestore с помощью статического метода make($path) и помещу в него нужные значения.

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']);
}

Как вы можете видеть, мы добавляем запрос banner_notification в хранилище. Под капотом Valustore конвертирует его в JSON и сохраняет в файл settings.json. Пакет полностью управляет этим файлом, если его нет, то он его создаст, а если мы удалим все значения, то он его удалит.

API использует практически все теже методы, что и кеш-хранилище Laravel, поэтому с ним просто работать.

Теперь вы можете получить доступ к этим настройкам из других мест вашего приложения. Для этого вам нужно создать экземпляр Valuestore с тем же путем, который мы указывали ранее.

// Контроллер...
public function __invoke()
{ $settings = Valuestore::make(storage_path('app/settings.json')); return view('homepage', ['settings' => $settings]);
}
// Шаблон...
@if($settings->has('banner_notification')) <div class="banner-notification"> {{ $settings->get('banner_notification') }} </div>
@endif

Valuestore это отличный способ хранить свободные значения, которые не нужны в базе данных. Никаких миграций, никаких моделей, только JSON файл, с вашими настройками. Идеально для базовых пар ключ/значение. Просто убедитесь, что файл настроек находится не в общедоступном месте.

В пакете также есть масса других удобных методов для работы с сохраненными данными, которые вам стоит посмотреть.

Хотя это всё, что вам нужно для начала, но следующие советы вам будут очень полезны при работе с Valuestore.

Привязка к контейнеру

В предыдущем примере видно, что нам пришлось создавать Valuestore несколько раз, и мы переписываем логику инстанцирования в нескольких местах, то почему бы нам не привязать настройки к контейнеру, чтобы это логика находилось в одном месте. Это также даст нам возможность внедрять Valuestore в контроллеры.

Для начала мы создадим наш собственный класс Settings, который расширяет Valuestore.

namespace App;
use SpatieValuestoreValuestore;
class Settings extends Valuestore
{ //
}

Далее мы привяжем экземпляр Settings к контейнеру как синглтон в сервис-провайдере.

// AppServiceProvider...
public function register()
{ $this->app->singleton(Settings::class, function () { return Settings::make(storage_path('app/settings.json')); });
}

Теперь мы можем внедрить наши настройки в контроллер при помощи DI:

public function update(Request $request, Settings $settings)
{ $settings->put('banner_notification', $request->banner_notification); return redirect()->back()->with(['notice' => 'Settings updated']);
}

Глобальный хелпер

Добавление глобального помощника settings() также будет очень полезным, особенно, если вы хотите получить доступ к настройкам в шаблонах. Хотя вы могли бы добиться этого и через view composer или передавая данные через контроллер, как я показал ранее, но, я считаю, что использование глобального хелпера гораздо проще и удобнее.

// helpers.php
function settings($key = null, $default = null) { if ($key === null) { return app(AppSettings::class); } return app(AppSettings::class)->get($key, $default);
}

В шаблонах теперь вы можете получить настройки через глобальный помощник. Это особенно удобно, когда параметр, например уведомление о баннере, нужен на каждой странице.

// Шаблон...
<div class="banner-notification"> {{ settings()->get('banner_notification') }} {{-- или --}} {{ settings('banner_notification') }}
</div>

Мне очень нравится простота, с которой этот пакет позволяет вам хранить свободные значения. Я всегда чувствовал, что хранение такого рода данных в базе данных неправильно. Если вам когда-нибудь понадобятся глобальные настройки приложений, то я настоятельно рекомендую ознакомиться с пакетом Spatie Valuestore. Спасибо, Spatie!

Автор: Tim Macdonald
Перевод: Demiurge Ash

Источник: laravel.demiart.ru