ADR-002 - Абстракція бази даних
ADR-002: Абстракція бази даних
Section titled “ADR-002: Абстракція бази даних”Запис рішення про архітектуру для шаблону доступу до об’єктно-орієнтованої бази даних XOOPS.
Статус
Section titled “Статус”Прийнято - Основний шаблон починаючи з XOOPS 2.0
Контекст
Section titled “Контекст”XOOPS потребувала стратегії взаємодії з базою даних, яка б:
- Абстрагувати специфічний для бази даних синтаксис SQL
- Забезпечте узгоджені операції CRUD у всіх модулях
- Увімкніть автоматичну очистку та видалення даних
- Підтримка майбутніх змін механізму бази даних
- Спростіть звичайні операції для розробників
Альтернативами були:
- Необроблений SQL у всій кодовій базі
- Повний ORM (Doctrine, Eloquent)
- Спеціальна легка абстракція
Діаграма прийняття рішень
Section titled “Діаграма прийняття рішень”graph TB subgraph "Application Layer" A[Module Code] B[Handler Methods] end
subgraph "Abstraction Layer" C[XoopsObjectHandler] D[XoopsPersistableObjectHandler] E[Criteria System] end
subgraph "Database Layer" F[XoopsDatabase] G[MySQLDatabase] H[PDO Wrapper] end
subgraph "Storage" I[(MySQL/MariaDB)] end
A --> B B --> C B --> D C --> E D --> E E --> F F --> G F --> H G --> I H --> IРішення
Section titled “Рішення”Ми запровадимо шаблон обробника за допомогою:
1. XoopsObject - Контейнер даних
Section titled “1. XoopsObject - Контейнер даних”Кожна сутність даних розширює XoopsObject:
class Item extends XoopsObject{ public function __construct() { $this->initVar('id', XOBJ_DTYPE_INT, null, false); $this->initVar('title', XOBJ_DTYPE_TXTBOX, '', true, 255); $this->initVar('content', XOBJ_DTYPE_TXTAREA, '', false); $this->initVar('status', XOBJ_DTYPE_INT, 0, false); }}2. Обробник - менеджер операцій
Section titled “2. Обробник - менеджер операцій”Кожен об’єкт має відповідний обробник:
class ItemHandler extends XoopsPersistableObjectHandler{ public function __construct($db) { parent::__construct($db, 'mymodule_items', Item::class, 'id', 'title'); }
// CRUD methods inherited: // - create(), get(), insert(), delete() // - getObjects(), getCount(), getAll()}3. Критерії - конструктор запитів
Section titled “3. Критерії - конструктор запитів”Умови об’єктно-орієнтованого запиту:
$criteria = new CriteriaCompo();$criteria->add(new Criteria('status', 1));$criteria->add(new Criteria('created', time() - 86400, '>='));$criteria->setSort('created');$criteria->setOrder('DESC');$criteria->setLimit(10);
$items = $handler->getObjects($criteria);Константи типу даних
Section titled “Константи типу даних”// Variable types with automatic sanitizationXOBJ_DTYPE_INT // IntegerXOBJ_DTYPE_TXTBOX // Single-line text (escaped)XOBJ_DTYPE_TXTAREA // Multi-line text (escaped)XOBJ_DTYPE_EMAIL // Email validationXOBJ_DTYPE_URL // URL validationXOBJ_DTYPE_ARRAY // Serialized arrayXOBJ_DTYPE_OTHER // No processingXOBJ_DTYPE_FLOAT // Floating pointУспадкування обробника
Section titled “Успадкування обробника”classDiagram class XoopsObjectHandler { <<abstract>> #db: XoopsDatabase +create(): XoopsObject +get(id): XoopsObject +insert(object): bool +delete(object): bool }
class XoopsPersistableObjectHandler { +getObjects(criteria): array +getCount(criteria): int +getAll(criteria): array +deleteAll(criteria): bool +updateAll(field, value, criteria): bool }
class ItemHandler { +getPublishedItems(): array +getByCategory(catId): array }
XoopsObjectHandler <|-- XoopsPersistableObjectHandler XoopsPersistableObjectHandler <|-- ItemHandlerНаслідки
Section titled “Наслідки”Позитивно
Section titled “Позитивно”- Узгодженість: усі модулі використовують однакові шаблони
- Безпека: автоматичний вихід запобігає введенню SQL
- Простота: звичайні операції вимагають мінімум коду
- Ремонтопридатність: зміни рівня бази даних не впливають на модулі
- Тестованість: обробники можуть бути використані для тестування
Негативний
Section titled “Негативний”- Продуктивність: додаткові накладні витрати на абстракцію
- Складність: крива навчання для нових розробників
- Обмеження: для складних запитів може знадобитися необроблений SQL
- Проблема N+1: немає вбудованого швидкого завантаження
Пом’якшення
Section titled “Пом’якшення”- Продуктивність: кешування часто використовуваних об’єктів
- Складні запити: Дозволити необроблений SQL за потреби
- N+1: використовуйте getAll() із відповідними критеріями
Еволюція до XOOPS 4.0
Section titled “Еволюція до XOOPS 4.0”flowchart LR subgraph "Current (2.5.x)" A[XoopsDatabase] B[Handlers] C[Criteria] end
subgraph "Future (4.0.x)" D[PDO/DBAL] E[Repository Pattern] F[Query Builder] G[DI Container] end
A --> D B --> E C --> F D --> G E --> GXOOPS 4.0 плани:
- Доктрина DBAL для абстракції бази даних — Обробники заміни шаблону сховища — Конструктор запитів для складних запитів
- Повна інтеграція контейнера PSR-11
Приклади коду
Section titled “Приклади коду”Базовий CRUD
Section titled “Базовий CRUD”$helper = Helper::getInstance();$handler = $helper->getHandler('Item');
// Create$item = $handler->create();$item->setVar('title', 'New Item');$handler->insert($item);
// Read$item = $handler->get($id);$title = $item->getVar('title');
// Update$item->setVar('title', 'Updated Title');$handler->insert($item);
// Delete$handler->delete($item);Складний запит
Section titled “Складний запит”$criteria = new CriteriaCompo();$criteria->add(new Criteria('status', 'published'));$criteria->add(new Criteria('category_id', '(1,2,3)', 'IN'));$criteria->add(new Criteria('created', strtotime('-30 days'), '>='));$criteria->setSort('views');$criteria->setOrder('DESC');$criteria->setLimit(10);$criteria->setStart(0);
$items = $handler->getObjects($criteria);$total = $handler->getCount($criteria);Пов’язані рішення
Section titled “Пов’язані рішення”- ADR-001: Модульна архітектура
- ADR-003: Smarty Template Engine
Посилання
Section titled “Посилання”- Мартін Фаулер - Шаблони архітектури корпоративних додатків
- Концепції доменного дизайну
- Шаблони Active Record проти Data Mapper
#xoops #architecture #adr #database #handler #design-decision