Слои данных: Cycle, DLE SDK, QueryBuilder v200.4.1
Какой слой брать под таблицу: Cycle ORM для таблиц модуля, DLE SDK для ядра DLE, QueryBuilder для generic-загрузки.
Зачем: в Admin три способа достать строку из БД, и выбор не вкусовой. Ошибка стоит дорого: миграции Cycle на таблицах DLE ломают обновление движка, а сырой SQL по таблицам модуля обходит EntityManager.
Правило одной строки
| Таблица | Слой | Чем |
|---|---|---|
Таблицы вашего модуля (api_*, dc_*, свои) | Cycle ORM | Entity + EntityManager |
Ядро DLE (post, users, comments, category, …) | DLE SDK | DcApi / TableQuery |
| Любая таблица, нужен generic SELECT/CRUD без схемы | QueryBuilder | DataLoaderService |
post, users и comments — только через SDK. Cycle Entity на них не заводим: схема этих таблиц принадлежит движку и меняется в релизах DLE. Двойная запись (Cycle + SDK) в одну таблицу запрещена.
Cycle ORM — таблицы модуля
Всё, что создаёт и версионирует сам модуль. Схему готовит SchemaSyncService (debug → «на лету», иначе файлы при расхождении). Гайд: Схема шлюза БД и автор записи.
$entity = new ApiKey();
$entity->setTitle('Мобильное приложение');
$this->em->persist($entity);
$this->em->run();Подробности: DatabaseGateway.
DLE SDK — ядро движка
SDK поставляется вместе с Admin: devcraft/src/sdk/dle/, namespace DevCraft\Dle\{Schema,Fluent,Xfield,Sdk}, глобальный фасад DcApi. Прежние имена DleApi\* работают через алиасы классов и будут удалены в следующем мажоре. Автозагрузка идёт через devcraft/vendor/autoload.php, поднимается в devcraft/init.php — отдельный bootstrap и пакет DLE API не нужны.
DcApi::news()->withTitle('Заголовок')->withCategory([1, 2])->create();
$rows = DcApi::query('post')->where('approve', '1')->orderBy('date')->limit(10)->fetchAll();Что даёт SDK поверх сырого SQL:
- ~60 схем таблиц ядра с белым списком колонок (
SchemaRegistry) — опечатка в колонке падает исключением, а не пустой выборкой; - виртуальные связи (
RelationMap) для CSV-полей вродеpost.category; - фильтры по доп. полям (
whereXfield()) и каталог xfields (DcApi::modifyXfield()); - кеш чтения через
CacheControl.
Полный список фасадов: DLE API → reference/sdk.
Экспорт плагина (install.xml / ZIP)
Снимок строки plugins + операций plugins_files в XML (как download в админке DLE):
use DevCraft\Dle\Sdk\Presenter\PluginPresenter;
(new PluginPresenter())->withName('DLE-API')->export(); // → Paths::pluginExports()/{slug}_v{version}.xml
(new PluginPresenter())->withName('DLE-API')->export(null, true); // ZIP: XML в корне + plugins.filelistКаталог по умолчанию задаётся в настройках Admin (Пути → путь экспорта плагинов) и читается через Paths::pluginExports().
QueryBuilder — generic-слой
Когда схема не нужна: свои таблицы, административные списки, INSERT/UPDATE/DELETE через DataLoaderService. См. DataLoader и QueryBuilder.
Мост SDK ↔ QueryBuilder
Слои связывает фабрика на стороне SDK. QueryBuilder про схемы DLE ничего не знает и зависимости на них не получает.
// Schema-валидация + generic-загрузка с кешем DataLoaderService
$rows = DcApi::query('post')->where('approve', '1')->limit(10)->toQueryBuilder()->load();
// Готовый QueryBuilder → Schema-aware запрос
$rows = TableQuery::fromQueryBuilder(QueryBuilder::create('users')->withLimit(5))->fetchAll();Мост переносит только то, что выразимо в обоих слоях:
| Переносится | Не переносится |
|---|---|
columns, равенства, order, limit, offset | LIKE (%значение), отрицание (!значение) |
| Первичный ключ схемы | RelationMap (post.category), whereXfield() |
Несовместимое условие даёт SdkException с кодом query_bridge_unsupported, а таблица вне SchemaRegistry (например api_keys) — InvalidArgumentException: это и есть граница «ядро DLE ↔ таблицы модуля».
Проверка логики моста без БД: php devcraft/src/sdk/dle/Fluent/query_bridge.selfcheck.php.