Docs

Глобальный EAV

uticms.eav · verified 2026-07-14

Обзор

Scope
Глобальная подсистема custom fields под app/Services/Eav и её таблицы БД

Ключевые понятия

Custom Field
Определение типизированного активного/обязательного/системного поля для entity_type.
Typed Value
Значение, хранимое ровно в одной колонке, выбранной FieldType: text, int, float, bool или JSON.
Field Extension
Поведение, специфичное для entity type, применяемое вокруг обработки field type.
Locale Key
Компонент locale в идентичности custom field value; по умолчанию — пустая строка.
Entity Type
Стабильный строковый ключ в custom_fields.entity_type и custom_field_values.entity_type; один класс модели соответствует одному entity_type.
Has Custom Fields
Eloquent trait, связывающий модель с глобальными custom_field_values через customFieldEntityType().

Структура

  • Definition Tables
    • Fieldscustom_fields
    • Translationscustom_field_translations
    • Optionscustom_field_options
  • Value Tablecustom_field_values
  • Services
    • RegistryCustomFieldEntityRegistry
    • CacheCustomFieldDefinitionCache
    • PipelineValuePipeline
    • Type RegistryFieldTypes/FieldTypeRegistry
    • ExtensionsCustomFieldExtensionRegistry
    • FormsEav/Filament/

Факты

  • custom_fields хранит entity type, name, type, data, sort и флаги activity/requirement/system; translations и options — отдельные дочерние таблицы. authoritative
  • custom_field_values уникален по field_id, entity_type, entity_id и locale. authoritative
  • custom_field_values имеет колонки value_text, value_int, value_float, value_bool и value_json. authoritative
  • Таблица values индексирует entity lookup, locale и типизированную фильтрацию по entity type, field, locale и каждому scalar value; создание text index зависит от диалекта БД. authoritative
  • Директория field types реализует text, long text, number, boolean, date, datetime, select, multiselect и file. authoritative
  • ValuePipeline выполняет extensions before store, field type store, затем extensions after store. authoritative
  • ValuePipeline выполняет field type load до afterLoad processing extensions. authoritative
  • ValuePipeline объединяет ошибки валидации FieldType с ошибками валидации каждого зарегистрированного extension. authoritative
  • HasCustomFields требует customFieldEntityType(); опциональный customFieldEntityLabel() управляет видимостью в admin registry; модели field/value по умолчанию — App\Models\CustomField и App\Models\CustomFieldValue. authoritative
  • EavServiceProvider обнаруживает каждый класс app/Models и modules/*/Models с HasCustomFields и регистрирует его через CustomFieldEntityRegistry::registerFromModel при boot. authoritative
  • Когда customFieldEntityLabel возвращает null, registerFromModel пропускает entity, и она не появляется в селекторах entity в CustomFieldResource. authoritative
  • User использует HasCustomFields с entity_type user и label Пользователь (user); values сохраняются в custom_field_values с entity_type user и entity_id равным users.id. authoritative
  • HasCustomFields предоставляет getCustomFieldValue, setCustomFieldValue, setCustomFieldValues, getAllCustomFieldValues, loadCustomFields, relation customFieldValues и query scopes whereField или whereFields. authoritative
  • CustomFieldsFormHelper строит Filament schema по entity_type; Edit pages используют fillCustomFieldsData и extractFromData плюс saveValues после сохранения parent record. authoritative

Инструкции

Connect Model

  1. добавить trait HasCustomFields к Eloquent-модели
  2. реализовать customFieldEntityType, возвращающий уникальный стабильный snake-case key
  3. реализовать customFieldEntityLabel, когда entity должна появляться в селекторах CustomFieldResource
  4. полагаться на auto-discovery EavServiceProvider или вызвать CustomFieldEntityRegistry::registerFromModel с именем модуля для module-owned entities
  5. создать field definitions в admin с matching entity_type
  6. подключить Filament resource form и save hooks через CustomFieldsFormHelper, когда нужно admin editing

Add Field Type

  1. реализовать контракт FieldType для validation, storage, loading и form behavior
  2. зарегистрировать его в FieldTypeRegistry
  3. проверить typed persistence и влияние на query/index
  4. добавить или обновить Filament form integration

Add Entity Extension

  1. реализовать custom field extension для целевого entity type
  2. зарегистрировать его в CustomFieldExtensionRegistry
  3. проверить beforeStore, afterStore, afterLoad и validation behavior

Правила

Architectural rule

Не пишите typed value columns напрямую, если у поля есть зарегистрированный type или extension; используйте EAV value pipeline.

Architectural rule

Не предполагайте, что глобальные EAV-таблицы применимы к Shop; у Shop отдельная EAV-схема и extension.

Примеры

User Model

use App\Services\Eav\Traits\HasCustomFields;

class User extends Authenticatable
{
    use HasCustomFields;

    public function customFieldEntityType(): string
    {
        return 'user';
    }

    public function customFieldEntityLabel(): ?string
    {
        return 'Пользователь (user)';
    }
}

app/Models/User.php

Read Value

$bio = $user->getCustomFieldValue('bio');
$users = User::whereField('department', 'sales')->get();

app/Services/Eav/Traits/HasCustomFields.php

Filament User Form

CustomFieldsFormHelper::buildSchema('user', $record)
CustomFieldsFormHelper::fillCustomFieldsData($record, $data)
CustomFieldsFormHelper::saveValues($record, 'user', $cfData)

app/Filament/Admin/Resources/UserResource.php