{"id":50529708,"url":"https://github.com/dimer47/backpack-server-export","last_synced_at":"2026-06-03T12:01:26.939Z","repository":{"id":360241283,"uuid":"1249300836","full_name":"dimer47/backpack-server-export","owner":"dimer47","description":"Server-side full export for Backpack CRUD with active filters, async support via queue jobs.","archived":false,"fork":false,"pushed_at":"2026-05-25T15:01:11.000Z","size":24,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T17:05:01.433Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dimer47.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-25T14:58:21.000Z","updated_at":"2026-05-25T15:01:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dimer47/backpack-server-export","commit_stats":null,"previous_names":["dimer47/backpack-server-export"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dimer47/backpack-server-export","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimer47%2Fbackpack-server-export","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimer47%2Fbackpack-server-export/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimer47%2Fbackpack-server-export/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimer47%2Fbackpack-server-export/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dimer47","download_url":"https://codeload.github.com/dimer47/backpack-server-export/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimer47%2Fbackpack-server-export/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33863264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-03T12:01:26.010Z","updated_at":"2026-06-03T12:01:26.925Z","avatar_url":"https://github.com/dimer47.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📦 Backpack Server Export\n\n![PHP](https://img.shields.io/badge/PHP-8.2%2B-777BB4?style=flat-square\u0026logo=php\u0026logoColor=white) ![Laravel](https://img.shields.io/badge/Laravel-10%20%7C%2011%20%7C%2012%2B-FF2D20?style=flat-square\u0026logo=laravel\u0026logoColor=white) ![Backpack](https://img.shields.io/badge/Backpack-6%20%7C%207-blue?style=flat-square) ![License](https://img.shields.io/badge/License-MIT-green?style=flat-square)\n\n\u003e Server-side full export for [Backpack for Laravel](https://backpackforlaravel.com/) CRUD panels with active filters, search, sort, and async queue support.\n\nUnlike the built-in DataTables client-side export (which only exports the **current page**), this package exports **all data** server-side, respecting the active filters, search term, column sort, and column visibility.\n\n## 🎉 Features\n\n- 📊 **Full server-side export** — all rows, not just the current page\n- 🔍 **Filter-aware** — respects active Backpack filters, search term, and sort order\n- 👁️ **ColVis-aware** — only exports columns visible to the user (respects the column visibility picker)\n- 🔐 **Permission-aware** — respects per-user column visibility and query scoping\n- ⚡ **Sync + Async** — direct download for small datasets, queue job for large ones\n- 📝 **3 formats** — XLSX (Excel), CSV, Markdown (GFM tables)\n- 🔌 **Pluggable progress tracker** — bring your own background task system or use the built-in no-op tracker\n- 🧩 **One-line integration** — just `use ServerExportOperation;` in your CRUD controller\n- 🌐 **Translated** — English and French included, easily extendable\n- 🎨 **Native UI** — button integrates seamlessly into the DataTables export bar\n\n## 📍 Installation\n\n```bash\ncomposer require dimer47/backpack-server-export\n```\n\nFor XLSX support, also install PhpSpreadsheet:\n\n```bash\ncomposer require phpoffice/phpspreadsheet\n```\n\n\u003e Without PhpSpreadsheet, only CSV and Markdown formats are available.\n\n## 🚀 Quick Start\n\nAdd the trait to any Backpack CRUD controller:\n\n```php\nuse Dimer47\\BackpackServerExport\\Operation\\ServerExportOperation;\n\nclass ArticleCrudController extends CrudController\n{\n    use ListOperation;\n    use ServerExportOperation; // That's it!\n    // ...\n}\n```\n\nA **\"Full Export\"** dropdown button will appear in the DataTables toolbar with XLSX, CSV, and Markdown options:\n\n```\n[ Export current view ▾ ]  [ Full Export ▾ ]  [ Column visibility ▾ ]\n                            ├─ Excel (XLSX)\n                            ├─ CSV\n                            └─ Markdown\n```\n\n## ⚙️ Configuration\n\nPublish the config file:\n\n```bash\nphp artisan vendor:publish --tag=backpack-server-export-config\n```\n\n```php\n// config/backpack-server-export.php\nreturn [\n    // Rows threshold above which export switches to async (queue job)\n    // 0 = always async, null = always sync\n    'async_threshold' =\u003e 1000,\n\n    // Available export formats\n    'default_formats' =\u003e ['xlsx', 'csv', 'md'],\n\n    // Queue name for async exports\n    'queue' =\u003e 'default',\n\n    // Temporary file storage path\n    'storage_path' =\u003e storage_path('app/tmp'),\n\n    // Chunk size for async processing\n    'chunk_size' =\u003e 500,\n\n    // How long to keep generated files (minutes)\n    'file_retention_minutes' =\u003e 60,\n];\n```\n\n## 🔧 Customization\n\nOverride these methods in your CRUD controller to customize the behavior:\n\n```php\nclass ArticleCrudController extends CrudController\n{\n    use ServerExportOperation;\n\n    // Custom export columns (default: auto-resolved from CRUD list columns)\n    protected function getServerExportColumns(): ?array\n    {\n        return [\n            ExportColumn::make('title')-\u003ewithLabel('Title'),\n            ExportColumn::make('author')-\u003ewithLabel('Author')-\u003ewithRelation('author', 'name'),\n            ExportColumn::make('status')-\u003ewithLabel('Status'),\n        ];\n    }\n\n    // Available formats (default: from config)\n    protected function getServerExportFormats(): array\n    {\n        return ['xlsx', 'csv'];\n    }\n\n    // Async threshold (default: from config)\n    protected function getServerExportAsyncThreshold(): ?int\n    {\n        return 500; // force async above 500 rows\n    }\n\n    // Custom filename\n    protected function getServerExportFilename(string $format): string\n    {\n        return 'my-articles-' . now()-\u003eformat('Y-m-d');\n    }\n}\n```\n\n## 📊 Supported Column Types\n\nThe package automatically resolves values for all standard Backpack column types:\n\n| Type | Resolution |\n|------|-----------|\n| `text`, `textarea`, `email`, `url`, `phone` | Direct attribute value |\n| `number` | Formatted with `decimals`, `dec_point`, `thousands_sep`, `prefix`, `suffix` |\n| `date`, `datetime` | Formatted with configurable format string |\n| `relationship`, `select`, `select_multiple` | Resolved via Eloquent relation + attribute |\n| `enum` | Mapped via `options` array, HTML stripped |\n| `select_from_array` | Mapped via `options` array |\n| `closure` | Closure executed, HTML stripped |\n| `custom_html` | `value()` executed, HTML stripped |\n| `boolean`, `check` | Translated \"Yes\" / \"No\" |\n| `model_function` | Method executed, HTML stripped |\n| `image` | URL/path returned as string |\n| `json` | Pretty-printed JSON string |\n\nComplex visual types (`ace_editor`, etc.) are automatically excluded from exports.\n\n## 🔄 Async Export with Progress Tracking\n\nFor large datasets, exports are processed as queue jobs. The package provides an `ExportProgressTrackerInterface` that you can implement to integrate with your own background task system.\n\n### Interface\n\n```php\nuse Dimer47\\BackpackServerExport\\Contracts\\ExportProgressTrackerInterface;\n\ninterface ExportProgressTrackerInterface\n{\n    public function create(int $userId, string $origin, array $metadata = []): string|int;\n    public function start(string|int $trackerId, int $total): void;\n    public function advance(string|int $trackerId, int $done): void;\n    public function complete(string|int $trackerId, string $filename): void;\n    public function fail(string|int $trackerId, string $error): void;\n    public function getDownloadUrl(string|int $trackerId): ?string;\n}\n```\n\n### Example: Custom Tracker\n\n```php\n// app/Adapters/MyExportTracker.php\nuse Dimer47\\BackpackServerExport\\Contracts\\ExportProgressTrackerInterface;\n\nclass MyExportTracker implements ExportProgressTrackerInterface\n{\n    public function create(int $userId, string $origin, array $metadata = []): int\n    {\n        return BackgroundTask::create([\n            'user_id' =\u003e $userId,\n            'type' =\u003e 'server_export',\n            'origin' =\u003e $origin,\n            'status' =\u003e 'pending',\n            'metadata' =\u003e $metadata,\n        ])-\u003eid;\n    }\n\n    public function start($id, int $total): void\n    {\n        BackgroundTask::where('id', $id)-\u003eupdate(['status' =\u003e 'processing', 'total' =\u003e $total]);\n    }\n\n    public function advance($id, int $done): void\n    {\n        BackgroundTask::where('id', $id)-\u003eupdate(['done' =\u003e $done]);\n    }\n\n    public function complete($id, string $filename): void\n    {\n        BackgroundTask::where('id', $id)-\u003eupdate(['status' =\u003e 'completed', 'filename' =\u003e $filename]);\n    }\n\n    public function fail($id, string $error): void\n    {\n        BackgroundTask::where('id', $id)-\u003eupdate(['status' =\u003e 'failed', 'error' =\u003e $error]);\n    }\n\n    public function getDownloadUrl($id): ?string\n    {\n        return null; // Let your UI handle downloads\n    }\n}\n\n// app/Providers/AppServiceProvider.php\n$this-\u003eapp-\u003ebind(ExportProgressTrackerInterface::class, MyExportTracker::class);\n```\n\n\u003e If no tracker is bound, the package uses a `NullProgressTracker` (no-op) — async exports still work, you just don't get progress feedback.\n\n## 🎨 Custom Formatters\n\nRegister your own export format:\n\n```php\nuse Dimer47\\BackpackServerExport\\Contracts\\ColumnFormatterInterface;\nuse Dimer47\\BackpackServerExport\\Services\\ServerExportService;\n\nclass JsonFormatter implements ColumnFormatterInterface\n{\n    public function getIdentifier(): string { return 'json'; }\n\n    public function generate(iterable $rows, array $columns, string $filePath): void\n    {\n        file_put_contents($filePath, json_encode(iterator_to_array($rows), JSON_PRETTY_PRINT));\n    }\n\n    public function getMimeType(): string { return 'application/json'; }\n    public function getFileExtension(): string { return 'json'; }\n}\n\n// In a service provider:\napp(ServerExportService::class)-\u003eregisterFormatter(new JsonFormatter());\n```\n\n## 🌐 Translations\n\nPublish and customize translations:\n\n```bash\nphp artisan vendor:publish --tag=backpack-server-export-lang\n```\n\nAvailable keys:\n\n| Key | EN | FR |\n|-----|----|----|\n| `button_label` | Full Export | Export complet |\n| `generating` | Generating... | Generation... |\n| `export_ready` | Export ready (:count rows) | Export pret (:count lignes) |\n| `export_started` | Export is being generated. Check background tasks. | Export en cours de generation. Consultez les taches en arriere-plan. |\n| `format_xlsx` | Excel (XLSX) | Excel (XLSX) |\n| `format_csv` | CSV | CSV |\n| `format_md` | Markdown | Markdown |\n\n## 🏗️ How It Works\n\n### Sync Mode (rows \u003c= threshold)\n\n1. User clicks \"Full Export\" \u003e chooses format\n2. JS collects active filters, search term, sort order, visible columns from DataTable state\n3. `POST /admin/resource/server-export?filters...` — filters in querystring, format in body\n4. Backend applies filters/search/sort on the CRUD query (no pagination)\n5. Resolves column values, generates file, returns download URL\n6. Browser downloads the file immediately\n\n### Async Mode (rows \u003e threshold)\n\n1-3. Same as sync\n4. Backend counts rows, creates a tracker entry, dispatches a queue job\n5. Returns immediately with `{ mode: 'async', tracker_id }`\n6. Queue job: authenticates as requesting user, bootstraps the CRUD controller, applies filters, processes rows by chunks, generates file, marks tracker as complete\n7. User sees progress in their notification center and downloads when ready\n\n## 📋 Requirements\n\n| Dependency | Version |\n|-----------|---------|\n| PHP | ^8.2 |\n| Laravel | ^10.0 \\| ^11.0 \\| ^12.0 \\| ^13.0 |\n| Backpack CRUD | ^6.0 \\| ^7.0 |\n| PhpSpreadsheet | ^1.29 \\| ^2.0 *(optional, for XLSX)* |\n\n## 📄 License\n\nMIT — see [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimer47%2Fbackpack-server-export","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimer47%2Fbackpack-server-export","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimer47%2Fbackpack-server-export/lists"}