[PHP, Анализ и проектирование систем, SQL] Идеальный каталог, базовая библиотека

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
05-Июл-2021 04:30

Всем привет.У меня было несколько публикаций по теме Entity Attribute Value, сокращенно EAV (паттерн программирования для хранения произвольных данных). За прошедшее время я допилил библиотеку для работы с EAV, и хотел бы поделиться с вами своими наработками.В библиотеке реализован базовый сценарий:
  • Создать сущность
  • Создать атрибут
  • Задать для сущности определённые атрибуты
  • Задать значение для атрибутов (создать предмет)
  • Сформировать хранилище для предметов в формате представления, материализованного представления, таблицы
  • Вычислить значения фильтров для поиска по предметам
  • Выполнить поиск по предметам
  • Добавить новый предмет
  • Добавить новый атрибут для сущности
  • Изменить значение атрибута (изменить характеристику предмета)
Изменения данных в пунктах 8-10, автоматически отражаются в хранилище данных не зависимо от формата выбранного в пункте 5.Если кто то чувствует в себе интерес к этой теме, то предлагаю присоединиться к разработке.Если вам хочется получить опыт в программировании чуть больше чем очередной HellowWord, то для вас тоже можно придумать интересный челендж.Для тех кто не в курсе, EAV это когда нам не надо в ручную проектировать и создавать новую таблицу в БД приложения для хранения информации о новой бизнес сущности, потому что у нас уже есть три таблицы и нам этого хватает для всего. В моей реализации шесть таблиц. Если хочется хранить данные не только как строки, то тогда это будет семь таблиц и плюс по одной таблице на каждый тип данных, но не в этом суть статьи, речь не столько о реализации, сколько о proof of concept , который можно потрогать руками.Предыдущие публикации на эту тему: Как установитьДля работы библиотеки потребуется СУБД PostgreSQL9+ и PHP7.4+ (в теории код можно упростить до PHP5, но тогда не будет type hitting, что не камильфо)
  • Скачать код из репозитория storage-for-all-things
  • Развернуть СУБД с помощью sql скрипта из файла configuration/install-tables-and-roles.sql.example
  • Настроить соединение с СУБД - отредактировать файл configuration/db_test.php.example
  • Переименовать configuration/db_test.php.example в configuration/db_test.php
  • Выполнить тест в файле tests/Integration/AutomatedProcessTest.php
Если все тесты прошли успешно, значит вы всё настроили без ошибок.Если какие то тесты упали, то значит мне надо править баги :) Буду благодарен за ваши баг репорты.Как использоватьКак использовать библиотеку вам будет понятно из кода и комментариев теста AutomatedProcessTest.Наружу из библиотеки торчит три ручки, три класса:
  • Operator AllThings\ControlPanel\Operator
  • Browser AllThings\ControlPanel\Browser
  • Schema AllThings\ControlPanel\Schema
Класс Operator работает непосредственно с данными. Класс Browser позволяет просматривать данные. Класс Schema создаёт объект СУБД для хранения данных и для сохранения согласованности данных (обновления по необходимости).О какой согласованности речь ? Собственно данные хранятся в трёх таблицах, но для удобства доступа к данным их можно хранить в трёх разных формах: представление, материализованное представление или таблица. Отсюда возникает задача согласования данных в исходных трёх таблицах и в той форме которая была выбран для хранения.Если, с представлением, синхронизация происходит автоматически на уровне СУБД, то с материализованным представлением и таблицей, необходимы дополнительные действия. За их выполнение отвечает класс Schema.Класс OperatorЭтот класс позволяет:1 Создать сущность (чертёж для создания предметов)
public function createBlueprint(
        string $code,
        string $storageKind = Storable::DIRECT_READING,
        string $title = '',
        string $description = ''
    ): IEssence
2 Создать атрибут (характеристика предмета)
public function createKind(
        string $code,
        string $dataType,
        string $rangeType,
        string $title = '',
        string $description = ''
    ): IAttribute
3 Для сущности добавить атрибут
public function attachKind(string $essence, string $kind): Operator
4 Создать предмет
public function createItem(
        string $essence,
        string $code,
        string $title = '',
        string $description = ''
    ): Nameable
5 Задать значение для атрибута (задать значение для характеристики предмета)
public function changeContent(
        string $thing,
        string $attribute,
        string $content
    )
6 Добавить предмету новый атрибут (задать значение для новой характеристики предмета)
public function expandItem(
        string $thing,
        string $attribute,
        string $value
    ): Operator
Используя эти шесть функций, мы можем вести базу данных нашего Универсального каталога, базу данных предметов.Но когда мы затевали наш Универсальный каталог, нашей задаче было не только создание базы данных с характеристиками предметов, прежде всего мы хотим наши данные отдавать на просмотр, в этом нам поможет класс Browser.Класс Browser
  • Вычислить параметры поиска
  • Выполнить поиск по заданным параметрам
1 Получить фильтры для выполнения поиска
public function filters(string $code): array
Фильтры вернуться в формате массива, который придётся разбирать руками, ни каких DTO для облегчения понимания не было сделано, извините, такие издержки у proof of concept.2 Выполнить поиск по заданным параметрам
public function filterData(string $code, $filters = []): array
Данные вернуться как массив, что делать с этим массивом пусть решает вызывающий код.Фильтры передаются как массив экземпляров классов AllThings\SearchEngine\ContinuousFilter и AllThings\SearchEngine\DiscreteFilter, это ещё два класса которые торчат из библиотеки, можно было конечно обойтись массивом со своей системой индексов, но в этом случае я не поленился и сделал DTO.Как задать параметры фильтрации можно посмотреть в тесте tests/Integration/AutomatedProcessTest.php.Я рассказал о том как задать данные и как их выгрузить, теперь мне осталось рассказать о том как данные быстро выдать и как данные быстро изменить. Всё это задачи класса Schema.Класс SchemaОсновное назначение этого класса, это:
  • Создать на основе сущности (на основе атрибутов) объект СУБД для хранения значений
  • Обновить значение в объекте СУБД при изменении значения атрибута сущности (конкретного предмета)
1 Создать хранилище для значений атрибутов
public function setup(): Schema
Что будет сделано ? Будет проверено какая форма был выбрана для хранения данных, это может быть:
  • Storable::DIRECT_READING - view
  • Storable::RAPID_OBTAINMENT - materialized view
  • Storable::RAPID_RECORDING - table
Далее будет создан соответствующий объект СУБД, и он будет заполнен данными в соответствии с тремя базовыми таблицами.2 Обновить значение при изменении этого значения в базовой таблице
public function refresh(?ICrossover $value = null): Schema
Тут мы видим ещё один класс, который просочился наружу из нашей библиотеки. ICrossover это интерфейс который хранит значение атрибута для конкретного предмета.Что произойдёт при вызове этого метода ? будет определена форма хранения данных и эти данные будет соответствующим способом обновлены.Если мы хотим что бы было обновлено только это значение, то в ICrossover следует передать новое значение атрибута, если значение не передать, то хранилище значений будет обновлено полностью.Последний нюанс о котором надо обязательно упомянуть, это то как мы сообщаем системе о том в какой форме мы хотим хранить наши данные для быстрого доступа.3 Задать форму хранения данных
public function changeStorage(string $storageKind): Schema
Как было сказано выше, формой может быть одна из следующих:
  • Storable::DIRECT_READING - view
  • Storable::RAPID_OBTAINMENT - materialized view
  • Storable::RAPID_RECORDING - table
О выборе формыВ статье Идеальный каталог, оптимизация выборки данных я приводил показатели быстродействия по всем формам.К этому можно добавить, то что форма представления и материализованного представления возможна только для хранения данных внутри одной БД. В то время как форма таблицы делает возможным хранение данных в отдельной СУБД.Сейчас конечно библиотека не даёт такой возможности, но это только proof of concept, который можно развить как угодно.Замеры производительностиНе будет замеров. Конечно без них статья сильно теряет в ценности. Но что бы написать тесты с профилированием потребуется один полноценный рабочий день и прямо сейчас я не обладаю такой роскошью.Откладывать публикацию очень не хочется и так вся эта история растянулась на три года :)ПланыКак вы могли заметить в статье речь идёт только о добавлении данных: добавить сущность, добавить атрибут, добавить значение, ни разу не было речи о том что бы что то удалить.Удаление на самом деле не реализовано, сделать не долго, но для proof of concept не требуется. Для использования в работе в библиотеке много не хватает, поэтому я для себя не вижу смысла доводить её до ума. Если кому то захочется, то пожалуйста, давайте сделаем. Мне для самого себя это не нужно.Мои контакты у меня в профиле и в репозитории.В будущем возможно соберусь и подробней распишу использование библиотеки с конкретным примером, или напишу тесты и померяю время выполнения операций. Зависит конечно от реакции и выбора сообщества.Спасибо за внимание.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_php, #_analiz_i_proektirovanie_sistem (Анализ и проектирование систем), #_sql, #_eav, #_php, #_analiz_i_proektirovanie_sistem (
Анализ и проектирование систем
)
, #_sql
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 16-Май 13:45
Часовой пояс: UTC + 5