Глобальные настройки приложения

Хранение глобальных настроек в Ларавел

В приложениях часто нужно хранить некоторые глобальные настройки, причем эти параметры не относятся к конкретной модели, например пользователю, а к системе в целом. Конечно, вы можете сделать это через 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
Перевод: Demiurge Ash