PHPackages                             mostafax/dynamic-hybrid-reporting-engine - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. mostafax/dynamic-hybrid-reporting-engine

ActiveLibrary[Database &amp; ORM](/categories/database)

mostafax/dynamic-hybrid-reporting-engine
========================================

Dynamic Hybrid Reporting Engine — query MySQL &amp; MongoDB via a unified JSON DSL, export to Excel/CSV/JSON, and power multi-tenant dashboards

v0.2.1(1mo ago)017MITPHPPHP ^8.2CI passing

Since Jun 9Pushed 1mo agoCompare

[ Source](https://github.com/mostafax2/dynamic-hybrid-reporting-engine)[ Packagist](https://packagist.org/packages/mostafax/dynamic-hybrid-reporting-engine)[ Docs](https://packagist.org/packages/mostafax/dynamic-hybrid-reporting-engine)[ RSS](/packages/mostafax-dynamic-hybrid-reporting-engine/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (10)Versions (6)Used By (0)

Dynamic Hybrid Reporting Engine
===============================

[](#dynamic-hybrid-reporting-engine)

**Enterprise reporting infrastructure for Laravel — MySQL + MongoDB, no SQL required**

[![PHP](https://camo.githubusercontent.com/13d44c226edc4671d7d176b844577a2ff00f3f21a96ada4563d539bf4bd2fed3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322b2d3737374242343f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://php.net)[![Laravel](https://camo.githubusercontent.com/5660c9b8594f90a45e0edaeb6f51d7165dfa309b5b468fff35b1fcede14e42c4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302532463131253246313225324631332d4646324432303f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://laravel.com)[![Redis](https://camo.githubusercontent.com/10d378e872d4ab981e57c1c837d6c73a79dc7ddcbfbb5b8975ace891b2b0af8a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f52656469732d52657175697265642d4443333832443f7374796c653d666c61742d737175617265266c6f676f3d7265646973)](https://redis.io)[![License](https://camo.githubusercontent.com/152aa2a37725b9fd554b28ff24d270f6071c67927a63e6d635a55c8e188e20c7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e3f7374796c653d666c61742d737175617265)](LICENSE)[![Version](https://camo.githubusercontent.com/d7c09099b54e2bf0dab4a25e6b908a3d8be51cf8e2990b17645f781109ebbf23/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f56657273696f6e2d312e302e302d626c75653f7374796c653d666c61742d737175617265)](CHANGELOG.md)

*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 —
**GitHub:** [github.com/mostafax2/dynamic-hybrid-reporting-engine](https://github.com/mostafax2/dynamic-hybrid-reporting-engine)
**Docs:** [mostafax2.github.io/dynamic-hybrid-reporting-engine](https://mostafax2.github.io/dynamic-hybrid-reporting-engine/)

---

Table of Contents
-----------------

[](#table-of-contents)

- [Overview](#-overview)
- [Requirements](#-requirements)
- [Quick Install](#-quick-install)
- [Detailed Setup](#-detailed-setup)
- [Visual Report Builder](#-visual-report-builder)
- [DSL Reference](#-dsl-reference)
- [PHP Facade](#-php-facade)
- [Blade Components](#-blade-components)
- [KPI Themes](#-kpi-themes)
- [REST API](#-rest-api)
- [Versioning](#-versioning)
- [Sharing &amp; Permissions](#-sharing--permissions)
- [Row-Level Security](#-row-level-security)
- [Templates](#-templates)
- [Security Model](#-security-model)
- [Custom Adapters](#-custom-adapters)
- [Configuration](#-configuration)
- [Database Tables](#-database-tables)
- [Architecture](#-architecture)
- [FAQ](#-faq)

---

🌟 Overview
----------

[](#-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-summary)

FeatureDescription🏗️ **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 &amp; 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 &amp; Tailwind, RTL-ready🏢 **Multi-Tenant**Tenant ID injected into every query; cache keys are per-tenant---

📋 Requirements
--------------

[](#-requirements)

### Required

[](#required)

DependencyVersionPHP`8.2+`Laravel`10 / 11 / 12 / 13``predis/predis``^2.0` or `^3.0`### Optional

[](#optional)

PackagePurpose`phpoffice/phpspreadsheet`XLSX export`livewire/livewire`Real-time filterable widgets`mongodb/laravel-mongodb`MongoDB data source---

⚡ Quick Install
---------------

[](#-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
----------------

[](#-detailed-setup)

### Step 1 — Install

[](#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

[](#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

[](#step-3--run-migrations)

```
php artisan migrate
```

### Step 4 — Environment Variables

[](#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)

[](#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)

[](#step-6--seed-demo-data-optional)

```
php artisan db:seed --class=ReportingEngineDemoSeeder
```

Creates:

- `demo_orders` — 80 MySQL rows
- `demo_events` — 120 MongoDB documents
- 5 demo reports saved in `dhr_reports`

---

🏗️ Visual Report Builder
------------------------

[](#️-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

[](#builder-panels)

PanelWhat you can do① SourcePick MySQL/MongoDB, connection, table — columns auto-load② JoinsVisual INNER/LEFT/RIGHT JOIN with alias support③ ColumnsDrag &amp; drop reorder, set label, format, width, visibility④ Formula ∑Write computed columns: `amount * tax_rate` or `IF(status='paid',1,0)`⑤ FiltersAND/OR tree builder — no SQL required⑥ AggregationGROUP BY + SUM/COUNT/AVG/MIN/MAX⑦ SortDraggable ORDER BY with ASC/DESC toggle⑧ PreviewLive paginated data preview with formatting⑨ HistoryVersion list + one-click rollback⑩ SharingGrant view/edit/admin to users, roles, or teams### Embed a Saved Report

[](#embed-a-saved-report)

```
{{-- Embed anywhere after saving in the builder --}}

{{-- Or via Facade --}}
$result = ReportingEngine::run('monthly-revenue');

{{-- Or via REST API --}}
POST /api/reporting/monthly-revenue/run
```

---

📐 DSL Reference
---------------

[](#-dsl-reference)

### Full Schema

[](#full-schema)

FieldTypeRequiredDescription`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:** `=` `!=` `>` `>=` ` '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
------------------

[](#-blade-components)

```
{{-- KPI cards — 6 visual themes --}}

{{-- Chart with Chart.js (SSR table fallback for no-JS) --}}

{{-- Filterable table with inline filters and export --}}

{{-- Export buttons only --}}

{{-- Livewire: real-time filter + sort + paginate --}}

```

---

🎨 KPI Themes
------------

[](#-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.

```
 {{-- default, white card with color top border --}}
 {{-- tinted background --}}
 {{-- dark slate background --}}
 {{-- frosted glass on color gradient --}}
 {{-- borderless, color bottom line --}}
 {{-- solid color fill --}}
```

---

🌐 REST API
----------

[](#-rest-api)

All endpoints are prefixed with `config('reporting-engine.routes.prefix')` (default: `api/reporting`).

### Report CRUD

[](#report-crud)

MethodEndpointDescription`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

[](#versioning)

MethodEndpointDescription`GET``/{id}/versions`List all versions`GET``/{id}/versions/{v}`Get a specific version`POST``/{id}/versions/{v}/rollback`Restore to a version### Sharing

[](#sharing)

MethodEndpointDescription`GET``/{id}/shares`List active shares`POST``/{id}/shares`Grant access`DELETE``/{id}/shares/{shareId}`Revoke access### Templates

[](#templates)

MethodEndpointDescription`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

[](#schema-introspection)

MethodEndpointDescription`GET``/schema/tables?source=mysql&connection=mysql`List tables`GET``/schema/columns?source=mysql&table=orders`Describe columns### RLS Policies

[](#rls-policies)

MethodEndpointDescription`GET``/rls-policies`List policies`POST``/rls-policies`Create policy`PUT``/rls-policies/{id}`Update policy`DELETE``/rls-policies/{id}`Delete policy---

🕑 Versioning
------------

[](#-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 &amp; Permissions
---------------------------

[](#-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
--------------------

[](#-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
-----------

[](#-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
-----------------

[](#️-security-model)

Every layer fires independently — compromising one does not bypass the others.

LayerMechanismProtects Against**Identifier Whitelist**`QuerySanitizer` — regex `/^[a-zA-Z_][a-zA-Z0-9_.]*$/` on all column/table namesColumn/table name injection**Formula Allowlist**`FormulaLexer` (character set) + `MySQLFormulaTranspiler` (backtick quoting)Expression injection**PDO Bindings**Laravel Query Builder — values always PDO parameters, never interpolatedSQL value injection**Field-Level ACL**`FieldAccessControl` — denied fields silently stripped; denied filter fields throw 422Sensitive field exposure**Row-Level Security**`RowLevelSecurityService` — per-role WHERE policies AND-merged automaticallyUnauthorised row access**Query Limits**`QueryValidator` — max rows, joins, conditions, aggregations enforced before any DB callResource exhaustion**Rate Limiting**`QueryLimitMiddleware` — per-user budget via Laravel RateLimiterAbuse / DoS**Tenant Isolation**Tenant ID injected into every query (MySQL WHERE / MongoDB `$match`)Cross-tenant data leakage---

🔌 Custom Adapters
-----------------

[](#-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
----------------

[](#️-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
------------------

[](#️-database-tables)

TablePurpose`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
---------------

[](#️-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
-----

[](#-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](#-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
---------

[](#-license)

MIT © 2026 [Mostafa Elbayyar](mailto:mostafa.m.elbiar2@gmail.com)

---

**Built with ❤️ for the Laravel community**

[⭐ Star on GitHub](https://github.com/mostafax2/dynamic-hybrid-reporting-engine) · [🐛 Report Bug](https://github.com/mostafax2/dynamic-hybrid-reporting-engine/issues) · [💡 Request Feature](https://github.com/mostafax2/dynamic-hybrid-reporting-engine/issues)

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance90

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

45d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/146624906?v=4)[Mostafa Elbayyar](/maintainers/mostafax2)[@mostafax2](https://github.com/mostafax2)

---

Tags

laravelexportmysqlreportingmongodbDSLdashboardanalyticssaasmulti-tenant

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/mostafax-dynamic-hybrid-reporting-engine/health.svg)

```
[![Health](https://phpackages.com/badges/mostafax-dynamic-hybrid-reporting-engine/health.svg)](https://phpackages.com/packages/mostafax-dynamic-hybrid-reporting-engine)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M136](/packages/laravel-pulse)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77922.3M186](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
