Download the PHP package mercurioplatform/tables without Composer
On this page you can find all versions of the php package mercurioplatform/tables. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download mercurioplatform/tables
More information about mercurioplatform/tables
Files in mercurioplatform/tables
Package tables
Short Description Reusable list/table engine for Laravel admin (Bootstrap 5 + jQuery + Blade).
License MIT
Homepage https://github.com/mercurioplatform/tables
Informations about the package tables
mercurioplatform/tables
Reusable list/table engine для админок на Laravel 13 + Bootstrap 5 + jQuery + Blade. Декларативные Resource-классы превращаются в полноценные admin-страницы (поиск, сортировка, фильтры, saved views, bulk/row actions, экспорт, prefs, history+undo) одной строкой роута.
Why
- 1 Resource-класс = 1 admin-страница.
Route::tablesPage('admin/products', ProductResource::class)— контроллер не нужен, страница, JSON-эндпоинты для bulk/row/export/prefs/log регистрируются автоматически, ресурс попадает вResourceRegistryбез дублирования в конфиге. - 5 путей расширения, не больше: подкласс
Field→cellView()на ячейке → слоты<x-tables::page>→ SCSS theme tokens → ключиconfig/tables.php.vendor:publish --tag=tables-views— эскейп-хатч, когда ничего из перечисленного не подошло. - Без vendor lock-in. Bootstrap 5 + jQuery + Blade-компоненты, без виртуального DOM и SPA-оверхеда. Страница рендерится сервером, AJAX подгружает только
<x-tables::table-root>.
Install
Опубликовать ресурсы:
JS- и SCSS-бандлы ассетов подключаются в Vite-конфиге хост-приложения (импорт из resources/{js,scss}/vendor/tables/).
Quickstart (30 секунд)
Namespace hint. Cell-fields (
Mercurio\Tables\Field\*) и form-fields для bulk/row schemas (Mercurio\Tables\Form\Field\*) делят именаTextFieldиNumberField. В Resource'е, использующем оба слоя, удобнее импортировать form-fields под алиасом:
Откройте /admin/products — рабочая страница со списком, поиском, сортировкой и пагинацией. Bulk/row actions, saved views, фильтры, экспорт включаются добавлением соответствующих методов в ProductResource (см. Features).
Examples
В репозитории есть examples/ — готовые demo-ресурсы на все пять Source-адаптеров (EloquentSource, ArraySource, SqlSource, HttpSource, FileSource CSV/JSONL). Это лучший способ увидеть, как поднимается каждый Source: copy-paste файла в app/Tables/Demo/, миграция + сидер, route-snippet — и demo-страницы работают.
После copy-paste откроется шесть URL'ов:
/admin/tables-demo/eloquent—App\Models\UserчерезEloquentSource/admin/tables-demo/array— справочник из 32 строк черезArraySource/admin/tables-demo/sql— таблицаtables_demo_ordersчерезSqlSource/admin/tables-demo/http— JSONPlaceholder черезHttpSource/admin/tables-demo/file-csv—currencies.csvчерезFileSource::csv()/admin/tables-demo/file-jsonl—instruments.jsonlчерезFileSource::jsonl()
examples/не попадает вvendor/послеcomposer require— он исключён через.gitattributes/composer.json#archive.exclude. Это сознательное архитектурное решение: вендор остаётся с одним только runtime-кодом. Examples живут на GitHub.
Quick-start (copy-paste): examples/README.md. Подробный разбор каждого demo и decision-tree «какой Source выбрать»: docs/examples.md.
JSON API
Любой ListResource может опционально отдавать JSON параллельно Blade-рендеру через Route::tablesApi(...). Macro независим от Route::tablesPage(...) — middleware наследуется от файла маршрутов (routes/api.php → api stack, routes/web.php → web stack), implicit-публикации нет.
Доступно из коробки:
?fields=id,number,total— sparse-fieldsets (whitelist черезApiConfig::allowFields).?format=raw|formatted|both— три режима сериализации значений; per-field overrides?format[total]=both&format[status]=raw(детали вdocs/json-api.md).?filter[status]=paid/?filter[total][gte]=1000— плоский AND-sugar, whitelist operator'ов через существующийField::filterable([Operator::...]).- POST с JSON-body или
?qb=<base64>для произвольного QB-дерева (OR-группы, NOT, вложенность) — см.docs/json-api.md. ?sort=-created_at,?q=…,?per_page=N,?page=N.?savedView=key— мерджится с пришедшимиfilter[..].?include=summary,savedViews,capabilities— опциональные блоки envelope'а.- self-описание ресурса через
?include=schemaили discovery-endpointGET /{uri}/schema— см.docs/json-api.md. - mutations через
POST /{uri}/mutate(cell / row / bulk, JSON body сop-дискриминатором) приapi()->allowMutations(true)— undo-probe через?include=undoToken, queued-bulk через 202 +progress_id; см.docs/json-api.md.
Read-only из коробки. Write активируется явным ApiConfig::allowMutations(true). Для публичного API под Sanctum/токены — Route::middleware('auth:sanctum')->group(...) в routes/api.php.
Полный контракт и error envelope: docs/json-api.md.
Registering resources
Route::tablesPage('admin/products', ProductResource::class) — основной путь. Макрос регистрирует 17 named routes для страницы (index, options, bulk/row actions, export, prefs, saved views, action log), и одновременно записывает FQN ресурса в Route::defaults('resource', ...) на каждый из них. При boot'е сервис-провайдер обходит все маршруты, собирает уникальные defaults['resource'] и вызывает ResourceRegistry::register(). Это даёт два важных свойства:
- Один источник правды.
Route::tablesPage(...)автоматически добавляет ресурс в реестр —config('tables.resources')для него заполнять не нужно. - Совместимо с
php artisan route:cache. Defaults сериализуются вместе сRouteCollection, поэтому enumeration работает и в проде, и в dev'е.
config('tables.resources') остаётся как опциональный override и нужен только в исключениях:
- Ресурс зарегистрирован через
Route::tablesResource(...)(controller-based, безdefaults('resource', ...)на роутах). - Ресурс используется без HTTP-маршрутов: CLI-команды, внешние интеграции, prerender'инг saved views в фоне.
- Хочется явно сузить набор ресурсов, по которым
SystemViewSyncerобходит БД.
SystemViewSyncer запускается в boot() на каждом non-console request'е и синхронизирует savedViews() ресурса с таблицей saved_views (типа system). Защищён fingerprint cache tables.sysviews.fp:{resourceKey} — повторных SQL-вызовов на неизменных объявлениях нет. Полностью выключается через config('tables.sync_system_views', false).
Features
- Saved views — system + user, синхронизируются из Resource-объявления через
php artisan tables:sync-saved-views. - Filter chips + Query Builder — chip / select / range / date / boolean + AST-фильтр через
?qb=base64(json). - Bulk actions — instant / confirm / form / queue (background).
- Row actions — link / inline / quick-edit form / popover-confirm.
- Action log + undo — окно отката для идемпотентных bulk.
- Prefs popover — видимые столбцы / density / page size, persisted на пользователя.
- Summary slot — KPI и funnel-cards над таблицей.
- Streaming export — CSV (default) + JSON + XLSX (opt-in), single endpoint, async fallback через
ExportJobDispatcher. - Localization — ru/en из коробки, namespace
tables::*, расширяется черезvendor:publish --tag=tables-lang. - Inline cell edit — декларативный
editableUsing(...)с policy / rules / transform / options и опциональной регистрацией route'а.
Saved views
SavedView::all() (вся выборка), SavedView::scope('name', label, scopeOrFilter). После изменения объявления — php artisan tables:sync-saved-views синхронизирует system-views в БД (для каждого key()).
Filters
Любой Field объявляется фильтруемым через ->filterable([Operator::In, Operator::Between, ...]). Для relation-полей (BelongsToField, BelongsToManyField) автокомплит подгружает опции через /<base>/options. Расширенный фильтр (Query Builder) включается автоматически — кнопка в filter-bar:right.
Bulk actions
Четыре kind: instant() (одним POST), confirm() (с превью), schema(...) (form в offcanvas), ->queue() (фоном через очередь Laravel).
Row actions
RowAction::link() — ссылка с иконкой; RowAction::make()->using(fn) — inline-handler; ->schema([...]) — quick-edit form в offcanvas; ->confirm()->preview(fn) — popover-подтверждение.
Action log
Append-only лог успешных bulk/row-действий пишется автоматически в tables_action_log. Двух-уровневое управление:
- Глобальный kill-switch —
config('tables.action_log.enabled', true).false→ writer не пишет ни одной записи; UI на странице тоже ничего не показывает. - Per-resource UI toggle —
actionHistoryEnabled(): trueна конкретном Resource. По умолчаниюfalse: записи в БД пишутся (если глобальный flagtrue), но HeaderAction «История» в page-head не появляется и offcanvas с журналом не доступен.true→ в header добавляется кнопка «История», offcanvas + undo (дляundoable()-actions в окнеundo_window_minutes) активны.
Сознательный design: писать заранее, чтобы при включении UI на ресурсе позже история была сохранена с момента deploy'а, а не с момента переключения flag'а.
Prefs
Per-user настройки видимых столбцов / density / page size — popover «Настроить таблицу» в filter-bar:right. Хранятся в tables_user_table_prefs (user_id, resource_key). URL > DB > defaults — приоритет разрешения.
Summary
Слот над таблицей для KPI/funnel-карточек. Объявляется на ресурсе:
Host может добавить собственные карточки — наследник SummaryCard + host-namespaced Blade-template (Blade::anonymousComponentNamespace(...) в AppServiceProvider). Опционально регистрируется по slug'у в config('tables.summary_cards'). Подробности и обработка ошибок рендера — docs/summary-cards.md.
Export
Стрим в нескольких форматах на текущее состояние списка (search + view + chips + qb + sort + visible columns) через единый endpoint ?format=csv|json|xlsx. CSV/JSON встроены, XLSX — opt-in (composer require openspout/openspout). Лимит — config('tables.export.sync_limit'); выше — ExportJobDispatcher (опционально) или HTTP 413. UI рендерит dropdown форматов автоматически, если зарегистрировано больше одного writer'а. Подробности и кастомный writer — docs/export.md.
Inline cell edit
Поле объявляется редактируемым через editableUsing(...) — один primary-метод, мерджащий policy / validation rules / опциональный transform / целевую колонку БД / опции для select-инпута. Старые shortcut-методы (editable, editColumn, editPolicy, editRules, editOptions) остаются и совместимы.
Pipeline на PATCH {base}/cells/{id}/{field}: policy → rules → transform → update() внутри транзакции. Любой Throwable из transform логируется как tables.cell_edit.transform_failed и возвращает 422 с translation-ключом tables::cell_edit.transform_failed.
Если ресурс read-only — переопределите ListResource::cellEditEnabled(): false, и route не будет регистрироваться вовсе (404).
Sticky layout
Для любой Route::tablesPage-страницы пакет автоматически включает поведение:
- Sticky checkbox-колонка (
.ap-table__chk) — фиксируется слева при горизонтальной прокрутке широкой таблицы. - Sticky actions-колонка (
.ap-table__more) — фиксируется справа при горизонтальной прокрутке. - Внутренний горизонтальный скролл — если полей много и контент не влазит в ширину карточки, появляется scrollbar внутри
.card, страница по горизонтали не разъезжается.
Поведение включено по умолчанию, без UI-тогглера. Реализация — чистый CSS position: sticky + .tables-scroll { overflow-x: auto } на внутреннем wrapper'е. Никакого JS, никакого custom-API.
Если host опубликовал views через vendor:publish --tag=tables-views ранее — повторите publish (новая разметка <div class="tables-scroll"> появилась в table-root.blade.php). Старые опубликованные views продолжат работать, но sticky-фичу не получат.
Sticky <thead> не реализован. Чистый CSS не может пиннить thead к верху viewport'а, когда у table-обёртки есть overflow-x: auto — .tables-scroll сама становится ближайшим scroll-контейнером для sticky-позиционирования. Решения с max-height (внутренний y-scroll, thead к верху обёртки) и JS-cloning (DataTables-подход) рассмотрены как follow-up; в текущем релизе sticky-thead отсутствует.
Чтобы выключить sticky-поведение колонок в host-приложении (host-side override после tables-стилей):
Localization
Пакет поставляется с двумя локалями — ru и en — namespace tables::* (12 групп: action_log, bulk, cell, confirm, export, filters, prefs, qb, row_actions, saved_views, shell, summary). Переключение через App::setLocale(). Runtime JS обращается к строкам через window.TablesI18n + helper tablesT(key, params).
Дефолты в config/tables.php для UI-меток (qb_button_label, export.button_label, user_prefs.popover_button_label, action_log.header_action_label) указаны как translation keys пакета — переопределение в хосте может передать как ключ ('app::custom.label'), так и готовую строку.
Подробности в docs/i18n.md.
Configuration
Все ключи — в config/tables.php (опубликуйте через vendor:publish --tag=tables-config). Ключевые:
guard— guard для policy/Gate-проверок (defaultadmin).default_per_page— fallback дляperPage()в Resource (default 25).partial_header— заголовок AJAX-частичного рендера (defaultX-Tables-Partial).js_event_prefix— префикс DOM-событий (tables:rendered,tables:loading,tables:total-changed).resources— массив FQN ResourceClass дляResourceRegistry. Опциональный — ресурсы, зарегистрированные черезRoute::tablesPage(...), попадают в реестр автоматически (см. Registering resources). Заполняйте только для CLI-only ресурсов,Route::tablesResource(...)и других исключений.sync_system_views— авто-вызовSystemViewSyncerвboot()(defaulttrue). Поставьтеfalse, чтобы полностью выключить синхронизацию system saved views (например, в read-replica окружении).action_log.enabled,action_log.undo_window_minutes,action_log.undo_snapshot_max_bytes— журнал и окно отката.bulk_progress.*— настройки фоновых bulk-actions (poll-интервал, job-class, chunk-size).export.sync_limit,export.chunk_size,export.csv_*,export.async_dispatcher— CSV-экспорт.shell.layout,shell.page_head_component,shell.flash_keys,shell.title_suffix— обёртка страницы.tables.*— имена БД-таблиц движка (для overrides на стороне хоста).
Extending
Пять путей, в порядке возрастания инвазивности:
-
Подкласс
Field— собственный тип ячейки. Достаточноprotected string $cellView = 'admin.tables._cell-foo'и Blade-шаблон с$value/$rowв скоупе. -
->cellView('partial.name')на ячейке существующего поля — без подкласса, переопределить только рендер ячейки. -
Слоты
<x-tables::page>—header,summary,empty-stateпринимают произвольный Blade. -
SCSS theme tokens — переопределить переменные пакета в собственном бандле (импорт
resources/scss/vendor/tables/_tokens.scssпосле собственных). - Config keys — поведение, не вёрстку (
tables.bulk_progress.poll_interval_ms,tables.export.sync_limit, …).
Эскейп-хатч: vendor:publish --tag=tables-views копирует blade-компоненты в resources/views/vendor/tables/ — приоритет публикации над пакетом.
Development
Тесты в пакет не вкладываются; регрессии проверяются на host-приложении.
JS dev-tooling (ESLint)
tables/package.json существует только для dev-инструментов: runtime-зависимости (jQuery, Bootstrap) поставляет host-приложение через Vite. package-lock.json не коммитится — по аналогии с composer.lock (конвенция library-package'а), чтобы host-приложение свободно резолвило версии своих зависимостей.
Upgrade from v1.1 to v1.2
Изменения, требующие действий на host-приложении:
-
Anonymous components namespace. Internal Blade refs пакета теперь используют namespaced синтаксис
<x-tables::page>,<x-tables::table-root>, и т.д. Если в host-шаблонах есть ссылки в старом формате<x-tables.page>, замените их: -
Host-override
Blade::anonymousComponentPathбольше не нужен. Если вAppServiceProvider::boot()(или другом сервис-провайдере) был добавлен workaround видаBlade::anonymousComponentPath(base_path('vendor/mercurioplatform/tables/resources/views/components'), 'tables')— удалите его. Пакет регистрирует namespace'tables'сам. -
Опубликованные views — переопубликовать. Структура
resources/views/vendor/tables/упрощена: подпапкаcomponents/tables/убрана, файлы переехали вcomponents/. Если делалиvendor:publish --tag=tables-views:Альтернатива — вручную: переместить
resources/views/vendor/tables/components/tables/*вresources/views/vendor/tables/components/, удалить пустуюtables/. -
config('tables.resources')стал опциональным. Ресурсы черезRoute::tablesPage(...)теперь регистрируются автоматически. Можно очистить массив, оставив в нём только CLI-only ресурсы и ресурсы подRoute::tablesResource(...). Подробности — Registering resources. php artisan route:cacheв production. Подтверждённо совместим с auto-registry: defaults сериализуются вRouteCollection. Если ещё не используется в деплое — добавьте, это снимет boot-стоимость регистрации ~17 маршрутов на каждый ресурс.
License
MIT © Timur Turdyev