← Предварительная загрузка · Вернуться к README · Преобразования данных →
Конфигурация
Публикация конфигурации
php artisan vendor:publish --tag="model_settings"
Команда публикует config/model_settings.php и миграцию пакета.
Доступные параметры
| Параметр | Значение по умолчанию | Назначение |
|---|---|---|
model | DragonCode\LaravelModelSettings\Models\Settings | Eloquent-модель для сохранённых настроек |
connection | Стандартное для приложения | Подключение к базе данных для модели и миграции |
table | settings | Таблица базы данных для модели и миграции |
casts | [] | Преобразования данных, выбранные по классу родительской модели и, при необходимости, ключу настройки |
Пакет читает следующие переменные окружения:
| Переменная | Значение по умолчанию |
|---|---|
MODEL_SETTINGS_DATABASE_CONNECTION | DATABASE_CONNECTION, затем стандартное подключение Laravel |
MODEL_SETTINGS_DATABASE_TABLE | settings |
Задайте подключение и таблицу до запуска миграции:
MODEL_SETTINGS_DATABASE_CONNECTION=mysql
MODEL_SETTINGS_DATABASE_TABLE=model_settings
Изменение этих параметров позже не переносит существующие записи.
Настройка преобразований данных
Устаревшая, но совместимая форма для всей модели по-прежнему поддерживается. Один класс преобразования обрабатывает все данные, принадлежащие классу модели:
'casts' => [
App\Models\User::class => App\Casts\UserSettingsPayloadCast::class,
],
Используйте карту по ключам, если для разных настроек нужны разные типы или обработка:
'casts' => [
App\Models\User::class => [
'profile' => App\Data\ProfileData::class,
'billing.credentials' => App\Casts\EncryptedSettingPayload::class,
],
],
Ключи сопоставляются точно. Точки не обозначают вложенный путь, а отсутствующий в карте ключ использует стандартное JSON-преобразование. Запись каждой модели задаётся либо строкой класса для всей модели, либо картой по ключам; символа подстановки внутри карты нет. Поддерживаемые контракты и пример шифрования описаны в разделе Преобразования данных.
Схема хранения
Опубликованная миграция создаёт следующие столбцы:
| Столбец | Назначение |
|---|---|
id | Первичный ключ строки настройки |
item_type | Morph-класс родительской модели или псевдоним |
item_id | Идентификатор родителя в виде строки длиной до 36 символов |
is_default | Отличает значения класса по умолчанию от переопределений моделей |
key | Ключ настройки |
payload | Данные, объявленные в миграции как jsonb |
created_at и updated_at | Временные метки Laravel |
Комбинация item_type, item_id, is_default и key уникальна. Индекс поиска по item_type,
is_default и item_id поддерживает чтение значений по умолчанию и области владельца.
Значения класса по умолчанию и переопределения моделей находятся в одной таблице. Пакет не создаёт вторую таблицу значений по умолчанию и не добавляет столбцы с метаданными шифрования.
Стандартный столбец item_id хранит не более 36 символов. Целочисленные, строковые, UUID- и
ULID-идентификаторы помещаются в эту схему, если их строковое представление не длиннее 36 символов.
Для более длинного пользовательского первичного ключа потребуется соответствующее изменение
миграции.
Значения класса по умолчанию используют item_id = '0' с is_default = true. Сохранённый владелец
с целочисленным ключом 0 или строковым '0' использует то же физическое значение item_id с
is_default = false, поэтому обе строки могут существовать для одного типа модели и ключа настройки.
Если данные уже существуют, изменение подключения, имени таблицы или псевдонимов morph map требует
самостоятельного переноса или обновления строк.
Обновление с более ранней версии 1.x
Этот выпуск меняет контракт выполнения вместе с миграцией дискриминатора хранения:
| Поведение прежней версии 1.x | Текущее поведение | Необходимое изменение приложения |
|---|---|---|
set($key, null), пустые строки, строки из пробелов и пустые массивы удаляли строку | set() сохраняет каждое JSON-значение без изменений | Замените вызовы удаления на forget($key) |
Пустые элементы setMany() удалялись в том же пакете | Каждый элемент setMany() сохраняется одним транзакционным upsert | Передайте удаляемые ключи отдельному вызову forgetMany() |
| Пустые ключи и ключи только из пробелов принимались | Нормализованные пустые ключи выбрасывают InvalidSettingKey | Переименуйте или удалите недопустимые ключи до обновления |
Для проверки наличия требовался all()->has($key) | has($key) отличает сохранённый JSON null от отсутствующего ключа | Используйте специализированный метод has() |
Сохранённое переопределение модели со значением null теперь скрывает заполненное значение класса
по умолчанию, пока forget() не удалит переопределение. Пользовательские преобразования данных
теперь получают пустые значения от обоих методов записи, а события create или update пользовательской
модели хранения получают их от set(). get() по-прежнему принимает только один аргумент; резервное
значение вызывающего кода и постоянный псевдоним put() не добавлены.
После обновления пакета опубликуйте новую миграцию и запустите её в режиме обслуживания приложения:
php artisan vendor:publish --tag="model_settings"
php artisan migrate
Миграция добавляет is_default, относит все прежние строки с item_id = '0' к значениям класса по
умолчанию, создаёт индексы с дискриминатором и затем удаляет прежний уникальный индекс. Она не
выводит ключи или данные настроек.
В прежней схеме 1.x значения класса по умолчанию и строки реального владельца с идентификатором 0
хранились одинаково. Поэтому миграция не может отличить добавленное вручную переопределение владельца
от значения по умолчанию и относит обе строки к значениям по умолчанию. После миграции проверьте
известные прежние данные владельцев с идентификатором 0 и установите is_default = false для строк,
которые являются переопределениями моделей.
Не запускайте прежнюю версию пакета с обновлённой схемой. Она не записывает дискриминатор и сохранит значения по умолчанию как переопределения. Разворачивайте миграцию и совместимую версию пакета в одной границе режима обслуживания.
Откат безопасен только до появления реального переопределения владельца с идентификатором 0.
Миграция останавливается до изменения схемы, если находит item_id = '0' с is_default = false,
поскольку прежняя схема не может представить такую строку без изменения её смысла. Удалите или
экспортируйте эти переопределения перед откатом. Безопасный откат восстанавливает прежний уникальный
индекс и удаляет is_default.
Замена модели хранения
Встроенная модель настроек объявлена как final. Вместо наследования настройте замену:
namespace App\Models;
use DragonCode\LaravelModelSettings\Casts\PayloadCast;
use Illuminate\Database\Eloquent\Model;
final class ApplicationSetting extends Model
{
protected $fillable = [
'item_type',
'item_id',
'is_default',
'key',
'payload',
];
public function __construct(array $attributes = [])
{
$this->setConnection(config('model_settings.connection'));
$this->setTable(config('model_settings.table'));
parent::__construct($attributes);
}
protected function casts(): array
{
return [
'item_id' => 'string',
'is_default' => 'boolean',
'payload' => PayloadCast::class,
];
}
}
Затем обновите конфигурацию:
'model' => App\Models\ApplicationSetting::class,
Замена должна оставаться совместимой с опубликованной схемой. Сохраните заполняемые атрибуты и
PayloadCast, если новая модель не реализует эквивалентную сериализацию.
Как минимум, новая модель должна сохранять следующее поведение:
| Требование | Причина |
|---|---|
Заполнять item_type, item_id, is_default, key и payload | Хранилище записывает эти атрибуты |
| Использовать настроенные подключение и таблицу | Миграция и репозиторий должны обращаться к одним строкам |
Преобразовывать item_id в string | Целые числа, строки, UUID и ULID хранятся в одном столбце |
Преобразовывать is_default в boolean | Ленивая и предварительная загрузка должны читать один дискриминатор области |
Преобразовывать payload через PayloadCast или эквивалент | Чтение и запись должны сохранять поведение JSON |
См. также
- Начало работы — публикация конфигурации и миграции.
- Преобразования данных — настройка прикладных типов данных.
- Справочник API — публичная поверхность пакета.