mostafax/dynamic-hybrid-reporting-engine
Composer 安装命令:
composer require mostafax/dynamic-hybrid-reporting-engine
包简介
Dynamic Hybrid Reporting Engine — query MySQL & MongoDB via a unified JSON DSL, export to Excel/CSV/JSON, and power multi-tenant dashboards
README 文档
README
Dynamic Hybrid Reporting Engine
Enterprise reporting infrastructure for Laravel — MySQL + MongoDB, no SQL required
One JSON DSL. MySQL + MongoDB. Visual no-code builder. Six KPI themes.
Enterprise versioning, sharing, and row-level security — all built in.
Author: Mostafa Elbayyar — mostafa.m.elbiar2@gmail.com
GitHub: github.com/mostafax2/dynamic-hybrid-reporting-engine
Docs: mostafax2.github.io/dynamic-hybrid-reporting-engine
Table of Contents
- Overview
- Requirements
- Quick Install
- Detailed Setup
- Visual Report Builder
- DSL Reference
- PHP Facade
- Blade Components
- KPI Themes
- REST API
- Versioning
- Sharing & Permissions
- Row-Level Security
- Templates
- Security Model
- Custom Adapters
- Configuration
- Database Tables
- Architecture
- FAQ
🌟 Overview
Dynamic Hybrid Reporting Engine is a Laravel package that delivers a complete reporting infrastructure in a single composer require. It provides a visual no-code report builder, a unified JSON DSL that works identically for MySQL and MongoDB, six live-switchable KPI card themes, and enterprise-grade features including versioning, RBAC sharing, row-level security, and Redis caching.
Feature Summary
| Feature | Description |
|---|---|
| 🏗️ Visual Report Builder | Full Vue 3 SPA at /report-builder — 10 panels, drag-and-drop columns, live preview, no SQL |
| 🔀 Unified JSON DSL | One schema for MySQL and MongoDB — fields, filters (nested AND/OR), aggregations, joins with aliases |
| ∑ Formula Engine | Computed columns pushed to SQL or MongoDB $addFields — full character-level security |
| 🎨 6 KPI Themes | flat · gradient · dark · glass · minimal · bold — live-switchable with a color picker |
| 🕑 Versioning | Auto-snapshot before every save; one-click rollback — nothing is ever lost |
| 👥 Sharing & RBAC | Share by user / role / team with view / edit / admin levels and optional expiry |
| 🔒 Row-Level Security | Per-role WHERE policies stored in dhr_rls_policies, AND-merged into every query automatically |
| 📋 Templates | Save any report as a reusable template; system templates ship with the package |
| ⚡ Redis Cache | Results cached by MD5 definition hash, tenant-scoped, tag-invalidated on update |
| 📤 3 Export Formats | CSV (UTF-8 BOM streaming) · XLSX (PhpSpreadsheet) · JSON — no temp files |
| 🧩 Blade Components | KPI cards, charts, tables, filters, export buttons — Bootstrap & Tailwind, RTL-ready |
| 🏢 Multi-Tenant | Tenant ID injected into every query; cache keys are per-tenant |
📋 Requirements
Required
| Dependency | Version |
|---|---|
| PHP | 8.2+ |
| Laravel | 10 / 11 / 12 / 13 |
predis/predis |
^2.0 or ^3.0 |
Optional
| Package | Purpose |
|---|---|
phpoffice/phpspreadsheet |
XLSX export |
livewire/livewire |
Real-time filterable widgets |
mongodb/laravel-mongodb |
MongoDB data source |
⚡ Quick Install
# 1. Install the package and Redis client composer require mostafax/dynamic-hybrid-reporting-engine predis/predis # 2. Publish config and run migrations php artisan vendor:publish --tag=reporting-engine-config php artisan vendor:publish --tag=reporting-engine-migrations php artisan migrate # 3. Seed demo data (optional) php artisan db:seed --class=ReportingEngineDemoSeeder
Done! Open /reporting-demo to see live components, /report-builder for the visual builder, and /api/reporting for the REST API.
🔧 Detailed Setup
Step 1 — Install
composer require mostafax/dynamic-hybrid-reporting-engine predis/predis
For local development with a path repository:
{
"repositories": [
{ "type": "path", "url": "packages/mostafax/reporting-engine" }
],
"require": {
"mostafax/dynamic-hybrid-reporting-engine": "@dev"
}
}
Step 2 — Publish Assets
# Config only php artisan vendor:publish --tag=reporting-engine-config # Migrations only php artisan vendor:publish --tag=reporting-engine-migrations # Vue builder assets php artisan vendor:publish --tag=reporting-engine-builder-js
Step 3 — Run Migrations
php artisan migrate
Step 4 — Environment Variables
# Redis (required) REDIS_HOST=127.0.0.1 REDIS_PORT=6379 # Route prefix (default: api/reporting) REPORTING_ROUTE_PREFIX=api/reporting # Auth middleware (leave empty to disable for dev) REPORTING_AUTH_MIDDLEWARE=auth:sanctum # Multi-tenancy (optional) REPORTING_TENANT_ENABLED=false REPORTING_TENANT_COLUMN=tenant_id
Step 5 — Build the Vue Builder (optional)
npm install --legacy-peer-deps php artisan vendor:publish --tag=reporting-engine-builder-js npm run build
Visit /report-builder — the full Vue 3 visual builder is now available.
Step 6 — Seed Demo Data (optional)
php artisan db:seed --class=ReportingEngineDemoSeeder
Creates:
demo_orders— 80 MySQL rowsdemo_events— 120 MongoDB documents- 5 demo reports saved in
dhr_reports
🏗️ Visual Report Builder
A full-page Vue 3 SPA at /report-builder:
/report-builder → create a new report
/report-builder/{id} → edit an existing report
Disable auth for development:
REPORTING_AUTH_MIDDLEWARE=
Builder Panels
| Panel | What you can do |
|---|---|
| ① Source | Pick MySQL/MongoDB, connection, table — columns auto-load |
| ② Joins | Visual INNER/LEFT/RIGHT JOIN with alias support |
| ③ Columns | Drag & drop reorder, set label, format, width, visibility |
| ④ Formula ∑ | Write computed columns: amount * tax_rate or IF(status='paid',1,0) |
| ⑤ Filters | AND/OR tree builder — no SQL required |
| ⑥ Aggregation | GROUP BY + SUM/COUNT/AVG/MIN/MAX |
| ⑦ Sort | Draggable ORDER BY with ASC/DESC toggle |
| ⑧ Preview | Live paginated data preview with formatting |
| ⑨ History | Version list + one-click rollback |
| ⑩ Sharing | Grant view/edit/admin to users, roles, or teams |
Embed a Saved Report
{{-- Embed anywhere after saving in the builder --}} <x-reporting-engine::report-widget report="monthly-revenue" :show-export="true" :per-page="25" /> {{-- Or via Facade --}} $result = ReportingEngine::run('monthly-revenue'); {{-- Or via REST API --}} POST /api/reporting/monthly-revenue/run
📐 DSL Reference
Full Schema
| Field | Type | Required | Description |
|---|---|---|---|
source |
string |
✅ | mysql or mongodb |
connection |
string |
— | DB connection name (default: source) |
table |
string |
✅ | Table or MongoDB collection |
fields |
array |
— | [{column, alias?}] |
computed |
array |
— | [{alias, expression, label?, format?}] |
column_meta |
array |
— | [{key, label, visible, order, format?, width?, align?}] |
aggregations |
array |
— | [{function, column, alias}] |
filters |
object |
— | {operator: AND/OR, conditions[]} — fully nestable |
group_by |
array |
— | ["field1", "field2"] |
order_by |
array |
— | [{column, direction}] |
pagination |
object |
— | {page, per_page} |
joins |
array |
— | MySQL only — [{type, table, alias?, first, operator, second}] |
Filter operators: = != > >= < <= like not_like in not_in between null not_null
Aggregation functions: sum count avg min max count_distinct
MySQL DSL Example
{
"source": "mysql",
"table": "orders",
"fields": [
{ "column": "id", "alias": "order_id" },
{ "column": "customer_name" },
{ "column": "amount" }
],
"aggregations": [
{ "function": "sum", "column": "amount", "alias": "revenue" },
{ "function": "count", "column": "id", "alias": "orders" }
],
"filters": {
"operator": "AND",
"conditions": [
{ "field": "status", "operator": "=", "value": "completed" },
{ "field": "amount", "operator": ">=", "value": 100 }
]
},
"group_by": ["status"],
"order_by": [{ "column": "revenue", "direction": "desc" }],
"pagination": { "page": 1, "per_page": 25 }
}
MongoDB DSL Example
{
"source": "mongodb",
"connection": "mongodb",
"table": "analytics",
"aggregations": [
{ "function": "sum", "column": "revenue", "alias": "total_revenue" },
{ "function": "count_distinct", "column": "userId", "alias": "unique_users" },
{ "function": "avg", "column": "revenue", "alias": "avg_revenue" }
],
"group_by": ["channel"],
"order_by": [{ "column": "total_revenue", "direction": "desc" }],
"pagination": { "page": 1, "per_page": 20 }
}
Engine auto-builds: $match → $addFields → $group → $project → $sort → $facet
Data + totalCount in a single round-trip. BSONArray/ObjectId/UTCDateTime normalised automatically.
Computed Fields (Formula Engine)
{
"computed": [
{
"alias": "margin",
"expression": "(amount - cost) / NULLIF(amount, 0) * 100",
"label": "Margin %",
"format": "percent"
},
{
"alias": "tax",
"expression": "amount * 0.15",
"label": "Tax Amount",
"format": "currency"
},
{
"alias": "tier",
"expression": "IF(amount > 1000, 'Premium', 'Standard')",
"label": "Customer Tier"
}
]
}
Allowed functions: IF COALESCE NULLIF ROUND ABS CEILING FLOOR CONCAT DATEDIFF DATE_FORMAT UPPER LOWER TRIM LENGTH NOW YEAR MONTH DAY
Security: All expressions pass through FormulaLexer (character allowlist) then MySQLFormulaTranspiler (backtick-quoted identifiers, function whitelist) before any SQL is built.
Column Metadata
{
"column_meta": [
{ "key": "order_id", "label": "Order #", "visible": true, "order": 0, "width": "80px", "align": "left" },
{ "key": "amount", "label": "Revenue", "visible": true, "order": 1, "format": "currency", "align": "right" },
{ "key": "cost", "label": "Cost", "visible": false, "order": 2 },
{ "key": "margin", "label": "Margin %", "visible": true, "order": 3, "format": "percent", "align": "right" }
]
}
format values: currency · percent · date · datetime · number · text
align values: left · center · right
Joins with Aliases
{
"source": "mysql",
"table": "orders",
"joins": [
{
"type": "left",
"table": "customers",
"alias": "c",
"first": "orders.customer_id",
"operator": "=",
"second": "c.id"
}
],
"fields": [
{ "column": "orders.id", "alias": "order_id" },
{ "column": "c.name", "alias": "customer" },
{ "column": "orders.amount", "alias": "amount" }
]
}
🔧 PHP Facade
use Mostafax\ReportingEngine\Support\Facades\ReportingEngine; // Run an ad-hoc DSL query $result = ReportingEngine::run([ 'source' => 'mysql', 'table' => 'orders', 'fields' => [ ['column' => 'id', 'alias' => 'order_id'], ['column' => 'status'], ['column' => 'amount'], ], 'computed' => [ ['alias' => 'tax', 'expression' => 'amount * 0.15', 'label' => 'Tax Amount', 'format' => 'currency'], ], 'aggregations' => [ ['function' => 'sum', 'column' => 'amount', 'alias' => 'revenue'], ['function' => 'count', 'column' => 'id', 'alias' => 'orders'], ], 'filters' => [ 'operator' => 'AND', 'conditions' => [ ['field' => 'status', 'operator' => '=', 'value' => 'completed'], ['field' => 'amount', 'operator' => '>=', 'value' => 100], ], ], 'order_by' => [['column' => 'revenue', 'direction' => 'desc']], 'pagination' => ['page' => 1, 'per_page' => 25], ]); $result->data; // array of rows (includes computed 'tax' column) $result->total; // total row count without LIMIT $result->metadata->executionTimeMs; // e.g. 8.4 $result->metadata->cacheHit; // true if served from Redis // Execute a saved report by ID use Mostafax\ReportingEngine\Application\Services\ExecutionService; $result = app(ExecutionService::class) ->runById('monthly-revenue', ['pagination' => ['page' => 2]]);
🧩 Blade Components
{{-- KPI cards — 6 visual themes --}} <x-reporting-engine::kpi-widget report="revenue-by-status" :cols="3" color="#0077A8" variant="glass" /> {{-- Chart with Chart.js (SSR table fallback for no-JS) --}} <x-reporting-engine::chart-widget report="revenue-by-status" chart-type="bar" label-column="status" value-column="total_revenue" /> {{-- Filterable table with inline filters and export --}} <x-reporting-engine::report-filter report="orders" :inline="true" /> <x-reporting-engine::report-widget report="orders" :show-export="true" :per-page="15" /> {{-- Export buttons only --}} <x-reporting-engine::report-export report="orders" :formats="['csv', 'xlsx', 'json']" /> {{-- Livewire: real-time filter + sort + paginate --}} <livewire:report-widget report="orders" :per-page="20" :show-filters="true" :show-export="true" />
🎨 KPI Themes
Pass variant="…" to switch the card style. The color prop sets --kpi-color inherited by all variants. Visit /reporting-demo for a live switcher and color picker.
<x-reporting-engine::kpi-widget report="id" variant="flat" /> {{-- default, white card with color top border --}} <x-reporting-engine::kpi-widget report="id" variant="gradient" /> {{-- tinted background --}} <x-reporting-engine::kpi-widget report="id" variant="dark" /> {{-- dark slate background --}} <x-reporting-engine::kpi-widget report="id" variant="glass" /> {{-- frosted glass on color gradient --}} <x-reporting-engine::kpi-widget report="id" variant="minimal" /> {{-- borderless, color bottom line --}} <x-reporting-engine::kpi-widget report="id" variant="bold" /> {{-- solid color fill --}}
🌐 REST API
All endpoints are prefixed with config('reporting-engine.routes.prefix') (default: api/reporting).
Report CRUD
| Method | Endpoint | Description |
|---|---|---|
POST |
/run |
Ad-hoc DSL execution |
GET |
/ |
List saved reports |
POST |
/ |
Create and save a report |
GET |
/{id} |
Get report details |
PUT |
/{id} |
Update report (auto-versions) |
DELETE |
/{id} |
Delete report |
POST |
/{id}/run |
Execute a saved report |
GET |
/{id}/export?format=csv |
Stream export (csv / xlsx / json) |
POST |
/{id}/clone |
Clone a report |
POST /api/reporting/run — Body:
{
"definition": {
"source": "mysql",
"table": "orders",
"fields": [{"column": "id"}, {"column": "amount"}],
"filters": {
"operator": "AND",
"conditions": [{"field": "status", "operator": "=", "value": "completed"}]
}
}
}
POST /api/reporting — Body:
{
"name": "Revenue by Status",
"description": "Monthly revenue grouped by order status",
"definition": { "source": "mysql", "table": "orders", "..." : "..." },
"change_note": "Initial version"
}
Versioning
| Method | Endpoint | Description |
|---|---|---|
GET |
/{id}/versions |
List all versions |
GET |
/{id}/versions/{v} |
Get a specific version |
POST |
/{id}/versions/{v}/rollback |
Restore to a version |
Sharing
| Method | Endpoint | Description |
|---|---|---|
GET |
/{id}/shares |
List active shares |
POST |
/{id}/shares |
Grant access |
DELETE |
/{id}/shares/{shareId} |
Revoke access |
Templates
| Method | Endpoint | Description |
|---|---|---|
GET |
/templates |
List templates |
POST |
/templates/from-report/{id} |
Save report as template |
POST |
/templates/{id}/instantiate |
Create report from template |
DELETE |
/templates/{id} |
Delete template |
Schema Introspection
| Method | Endpoint | Description |
|---|---|---|
GET |
/schema/tables?source=mysql&connection=mysql |
List tables |
GET |
/schema/columns?source=mysql&table=orders |
Describe columns |
RLS Policies
| Method | Endpoint | Description |
|---|---|---|
GET |
/rls-policies |
List policies |
POST |
/rls-policies |
Create policy |
PUT |
/rls-policies/{id} |
Update policy |
DELETE |
/rls-policies/{id} |
Delete policy |
🕑 Versioning
Every PUT /{id} automatically snapshots the previous definition before overwriting. The current state is always preserved — nothing is lost on rollback.
// List version history GET /api/reporting/{id}/versions // → [{ version_number: 3, saved_by: "user-id", change_note: "Added tax column", created_at: "..." }] // View a specific version GET /api/reporting/{id}/versions/2 // Roll back to v2 (current state auto-saved as v4 first) POST /api/reporting/{id}/versions/2/rollback
Pass a change_note when saving:
PUT /api/reporting/{id} { "name": "Revenue Report", "definition": {...}, "change_note": "Added margin column" }
👥 Sharing & Permissions
Share any report with individual users, roles, or teams. Three permission levels: view, edit, admin. Optional expiry date per grant.
// Grant view access to a role POST /api/reporting/{id}/shares { "shareable_type": "role", "shareable_id": "analyst", "permission": "view", "expires_at": "2026-12-31" } // Grant edit access to a specific user POST /api/reporting/{id}/shares { "shareable_type": "user", "shareable_id": "usr_123", "permission": "edit" } // List all active shares GET /api/reporting/{id}/shares // Revoke a share DELETE /api/reporting/{id}/shares/{shareId}
🔒 Row-Level Security
Policies stored in dhr_rls_policies are automatically AND-merged into every query for matching roles — no code changes required in individual reports.
// Analysts can only see completed orders POST /api/reporting/rls-policies { "role": "analyst", "table_name": "orders", "where_clause": { "operator": "AND", "conditions": [ { "field": "status", "operator": "=", "value": "completed" } ] } }
report_id: null— global policy (applies to all reports using that table)report_id: "uuid"— scoped to a specific report only
📋 Templates
// Save a report as a reusable template POST /api/reporting/templates/from-report/{reportId} { "name": "Monthly Revenue Template", "category": "sales" } // List templates (system + tenant) GET /api/reporting/templates?category=sales // → [{ id, name, category, is_system, definition }] // Create a report from a template POST /api/reporting/templates/{templateId}/instantiate { "name": "June 2026 Revenue" } // → Returns a new report DTO with a fresh UUID
🛡️ Security Model
Every layer fires independently — compromising one does not bypass the others.
| Layer | Mechanism | Protects Against |
|---|---|---|
| Identifier Whitelist | QuerySanitizer — regex /^[a-zA-Z_][a-zA-Z0-9_.]*$/ on all column/table names |
Column/table name injection |
| Formula Allowlist | FormulaLexer (character set) + MySQLFormulaTranspiler (backtick quoting) |
Expression injection |
| PDO Bindings | Laravel Query Builder — values always PDO parameters, never interpolated | SQL value injection |
| Field-Level ACL | FieldAccessControl — denied fields silently stripped; denied filter fields throw 422 |
Sensitive field exposure |
| Row-Level Security | RowLevelSecurityService — per-role WHERE policies AND-merged automatically |
Unauthorised row access |
| Query Limits | QueryValidator — max rows, joins, conditions, aggregations enforced before any DB call |
Resource exhaustion |
| Rate Limiting | QueryLimitMiddleware — per-user budget via Laravel RateLimiter |
Abuse / DoS |
| Tenant Isolation | Tenant ID injected into every query (MySQL WHERE / MongoDB $match) |
Cross-tenant data leakage |
🔌 Custom Adapters
use Mostafax\ReportingEngine\Contracts\DataSourceInterface; use Mostafax\ReportingEngine\Domain\DTOs\QueryDefinition; use Mostafax\ReportingEngine\Domain\DTOs\ExecutionResult; class PostgreSQLDataSource implements DataSourceInterface { public function supports(string $sourceType): bool { return $sourceType === 'pgsql'; } public function query(QueryDefinition $def): ExecutionResult { $rows = DB::connection('pgsql') ->table($def->table) ->get() ->toArray(); return new ExecutionResult($rows, $total, $metadata); } public function aggregate(QueryDefinition $def): ExecutionResult { /* ... */ } public function count(QueryDefinition $def): int { /* ... */ } } // Register in AppServiceProvider::boot() $this->app->make(DataSourceResolver::class) ->register('pgsql', new PostgreSQLDataSource());
⚙️ Configuration
// config/reporting-engine.php return [ // ========== Query Limits ========== 'limits' => [ 'max_rows' => 10_000, 'max_per_page' => 500, 'max_execution_seconds' => 30, 'max_joins' => 5, 'max_conditions' => 20, 'max_aggregations' => 10, ], // ========== Redis Cache ========== 'cache' => [ 'enabled' => env('REPORTING_CACHE_ENABLED', true), 'driver' => 'redis', // requires predis/predis 'ttl' => 300, // seconds ], // ========== Multi-Tenancy ========== 'multi_tenancy' => [ 'enabled' => env('REPORTING_TENANT_ENABLED', false), 'tenant_column' => env('REPORTING_TENANT_COLUMN', 'tenant_id'), ], // ========== Field ACL ========== 'field_acl' => [ 'always_deny' => ['password', 'api_key', 'secret'], 'role_deny' => [ 'analyst' => ['ssn', 'credit_card'], ], ], // ========== Blade ========== 'blade' => [ 'theme' => 'auto', // 'bootstrap' | 'tailwind' | 'auto' 'rtl_locales' => ['ar', 'fa', 'he', 'ur'], ], // ========== Routes ========== 'routes' => [ 'enabled' => true, 'prefix' => env('REPORTING_ROUTE_PREFIX', 'api/reporting'), 'middleware' => array_filter(['api', env('REPORTING_AUTH_MIDDLEWARE', 'auth:sanctum')]), ], ];
🗄️ Database Tables
| Table | Purpose |
|---|---|
dhr_reports |
Saved report definitions |
dhr_report_executions |
Execution audit log |
dhr_report_versions |
Full version history (auto-created on every update) |
dhr_report_shares |
Sharing permission grants |
dhr_report_templates |
Reusable report templates |
dhr_rls_policies |
Row-level security policies |
dhr_dashboards |
Dashboard configurations |
dhr_widgets |
Widget bindings |
🏛️ Architecture
The 8-step hardened pipeline fires on every report — ad-hoc or saved.
ReportEngine::run($dsl)
01 DslParser → raw array → typed, immutable QueryDefinition (MD5-hashed)
02 QueryValidator → enforce limits + operator/aggregation whitelist
03 QuerySanitizer → identifier regex + FormulaLexer character allowlist
04 FieldACL + RLS → strip denied fields; AND-merge RLS WHERE policies
05 Redis Cache → GET by definition hash (tenant-scoped key)
06 DataSourceResolver → MySQLDataSource | MongoDataSource | custom
07 Execute → data + total + metadata in one round-trip
08 Cache PUT + Event → store result; dispatch ReportExecuted event
// Export — streamed, no temp files use Mostafax\ReportingEngine\Application\Services\ExportService; return app(ExportService::class)->exportById( reportId: $id, format: $request->query('format', 'csv'), // csv | xlsx | json userRoles: $request->user()->roles(), ); // Clone a report POST /api/reporting/{id}/clone { "name": "Q2 Revenue Report" } // → New UUID, "Copy of…" name, same definition, shares not copied
❓ FAQ
Q: How do I change the API route prefix?
// config/reporting-engine.php 'routes' => ['prefix' => 'api/v2/reports']
Q: How do I disable authentication in development?
REPORTING_AUTH_MIDDLEWARE=
Q: Can I use a non-default Redis connection?
// config/reporting-engine.php 'cache' => [ 'driver' => 'redis', 'connection' => 'reporting', // any connection from config/database.php ],
Q: How do I add a field to the global deny list?
// config/reporting-engine.php 'field_acl' => [ 'always_deny' => ['password', 'api_key', 'secret', 'stripe_key'], ],
Q: Does it work with PostgreSQL?
Not out-of-the-box, but you can write a custom adapter in ~30 lines. See Custom Adapters above.
Q: How do I use it with multi-tenancy?
REPORTING_TENANT_ENABLED=true REPORTING_TENANT_COLUMN=tenant_id
Bind current_tenant_id in a middleware:
app()->bind('current_tenant_id', fn () => auth()->user()->tenant_id);
📄 License
MIT © 2026 Mostafa Elbayyar
Built with ❤️ for the Laravel community
mostafax/dynamic-hybrid-reporting-engine 适用场景与选型建议
mostafax/dynamic-hybrid-reporting-engine 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 16 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 06 月 04 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「mongodb」 「DSL」 「mysql」 「analytics」 「export」 「laravel」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 mostafax/dynamic-hybrid-reporting-engine 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 mostafax/dynamic-hybrid-reporting-engine 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 mostafax/dynamic-hybrid-reporting-engine 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Dibi is Database Abstraction Library for PHP
Generates Symfony2 documents, forms and CRUD
Feature complete, object oriented, composable, extendable Elasticsearch query DSL builder for PHP.
Elasticsearch DSL library
Expression executor, which allow to implement domain-specific language
DSL for writing sniffs for PHP_CodeSniffer
统计信息
- 总下载量: 16
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 40
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-04