В приложениях часто нужно хранить некоторые глобальные настройки, причем эти параметры не относятся к конкретной модели, например пользователю, а к системе в целом. Конечно, вы можете сделать это через 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 Spatie\Valuestore\Valuestore; 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(App\Settings::class); } return app(App\Settings::class)->get($key, $default); }
В шаблонах теперь вы можете получить настройки через глобальный помощник. Это особенно удобно, когда параметр, например уведомление о баннере, нужен на каждой странице.
// Шаблон... <div class="banner-notification"> {{ settings()->get('banner_notification') }} {{-- или --}} {{ settings('banner_notification') }} </div>
Мне очень нравится простота, с которой этот пакет позволяет вам хранить свободные значения. Я всегда чувствовал, что хранение такого рода данных в базе данных неправильно. Если вам когда-нибудь понадобятся глобальные настройки приложений, то я настоятельно рекомендую ознакомиться с пакетом Spatie Valuestore. Спасибо, Spatie!
Автор: Tim Macdonald
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.