Перейти к основному содержимому

← Начало работы · Вернуться к README · Предварительная загрузка →

Работа с настройками

Один сервис работает и со значениями по умолчанию, и со значениями моделей. Точка входа определяет, какая область читается или изменяется:

Точка входаОбласть
(new User)->defaultSettings()Значения по умолчанию для всех сохранённых моделей User
$user->settings()Итоговые настройки одного сохранённого пользователя

Общие значения по умолчанию​

Значения по умолчанию применяются ко всем сохранённым моделям с одним morph-классом Eloquent:

$defaults = (new User)->defaultSettings();

$defaults->set('timezone', 'UTC');
$defaults->set('notifications', ['email' => true]);

Читайте и удаляйте значения по умолчанию через тот же сервис:

$timezone = $defaults->get('timezone');
$all = $defaults->all();

$defaults->forget('timezone');

Для каждого класса модели значения по умолчанию независимы.

Переопределения для моделей​

set() создаёт настройку или заменяет её текущее значение:

$user->settings()->set('timezone', 'Europe/Paris');
$user->settings()->set('timezone', 'America/Toronto');

Изменяется только настройка этой модели. Остальные модели продолжают использовать собственное переопределение или общее значение по умолчанию.

get(), has() и all() выбирают значения с одинаковым приоритетом:

$timezone = $user->settings()->get('timezone');
$hasTimezone = $user->settings()->has('timezone');
$settings = $user->settings()->all();

all() возвращает Illuminate\Support\Collection с ключами по именам настроек.

get() принимает только ключ. Сначала он возвращает переопределение модели, затем сохранённое значение класса по умолчанию, а затем null. Метод не принимает резервное значение от вызывающего кода. has() отличает отсутствующий ключ от сохранённого JSON null:

if ($user->settings()->has('timezone')) {
$timezone = $user->settings()->get('timezone');
}

Например, одно переопределение заменяет только соответствующее значение по умолчанию:

(new User)->defaultSettings()->set('timezone', 'UTC');
(new User)->defaultSettings()->set('locale', 'en');

$user->settings()->set('timezone', 'Europe/Paris');

assert($user->settings()->all()->sortKeys()->all() === [
'locale' => 'en',
'timezone' => 'Europe/Paris',
]);

Удаление значения​

После удаления переопределения модели снова используется значение по умолчанию:

(new User)->defaultSettings()->set('timezone', 'UTC');

$user->settings()->set('timezone', 'Europe/Paris');
$user->settings()->forget('timezone');

assert($user->settings()->get('timezone') === 'UTC');

Чтобы удалить само значение по умолчанию, вызовите forget() через defaultSettings():

(new User)->defaultSettings()->forget('timezone');

Вызов forget() для отсутствующего ключа ничего не меняет.

Групповые изменения​

Используйте setMany() и forgetMany(), когда в одной области нужно изменить несколько ключей:

$user->settings()->setMany([
'timezone' => 'Europe/Paris',
'locale' => 'fr',
]);

$user->settings()->forgetMany(['timezone', 'locale']);

Оба метода принимают любой iterable. Перед записью setMany() нормализует каждый ключ. Если несколько входных ключей преобразуются в один сохранённый ключ, используется последнее значение. Все значения сохраняются; строки удаляют только forget() и forgetMany().

Непустой пакет setMany() выполняет один нативный upsert внутри транзакции. forgetMany() удаляет все перечисленные ключи одним запросом. Число запросов ограничено типом операции и не зависит от количества ключей.

Используйте purge(), чтобы полностью очистить текущую область:

$user->settings()->purge();

Для settings() метод purge() удаляет только переопределения этого владельца, после чего снова становятся видны сохранённые значения по умолчанию. Для defaultSettings() он удаляет значения по умолчанию этого класса модели, не затрагивая переопределения моделей. Все три групповых метода возвращают void.

JSON-значения​

set() и setMany() сохраняют JSON-значения без изменений:

ЗначениеРезультат
nullСохраняется
'' или строка только из пробеловСохраняется
[]Сохраняется
0Сохраняется
falseСохраняется
'0'Сохраняется

Сохранённый null считается существующим значением. has($key) возвращает true, а get($key) — null. Переопределение модели со значением null также скрывает заполненное значение класса по умолчанию, пока переопределение не будет удалено через forget().

Ключи настроек​

Ключами могут быть строки, целые числа или PHP-перечисления, реализующие UnitEnum:

enum SettingKey: string
{
case Timezone = 'timezone';
}

$user->settings()->set(SettingKey::Timezone, 'Europe/Paris');

$timezone = $user->settings()->get(SettingKey::Timezone);

Laravel сохраняет backed enum как его базовое значение, а pure unit enum — как имя варианта. При чтении, замене и удалении используйте тот же ключ или вариант перечисления.

Пустые ключи и ключи только из пробелов выбрасывают DragonCode\LaravelModelSettings\Exceptions\InvalidSettingKey. Проверка выполняется после нормализации целых чисел и перечислений в сохраняемую строку. Исключение не содержит отклонённый ключ или данные настройки.

Точки считаются обычными символами. Ключ mail.from.address — это один непрозрачный ключ настройки, а не вложенный путь:

$user->settings()->set('mail.from.address', '[email protected]');

$address = $user->settings()->get('mail.from.address');

Идентификаторы моделей​

Поддерживаются целочисленные, строковые, UUID- и ULID-первичные ключи.

Для изменения настроек модели нужен сохранённый владелец с ключом, отличным от null. Для несохранённой модели get() возвращает null, has() — false, а all() — пустую коллекцию без запроса переопределений. Методы set(), setMany(), forget(), forgetMany() и purge() выбрасывают InvalidSettingsOwnerException до выполнения запроса к хранилищу или чтения iterable.

Сохранённые модели с целочисленным идентификатором 0 или строковым '0' поддерживают те же операции чтения и изменения, что и любой другой сохранённый владелец. Дискриминатор области отделяет их переопределения от значений класса по умолчанию, хотя обе строки сохраняют item_id = '0'. Другие строковые ключи, включая '00', остаются допустимыми.

Настройки сохраняются для текущего morph-класса модели. Если после записи настроек добавить или изменить псевдоним в morph map, существующие значения item_type придётся обновить.

См. также​