base-api-scramble-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -0
- package/docs/AI-GUIDE-COMPLETE.md +372 -0
- package/docs/EXCEL-EXPORT-SERVICE.md +349 -0
- package/docs/EXPORT-DATA-PROVIDERS.md +340 -0
- package/docs/EXPORT-TEMPLATES.md +459 -0
- package/docs/LARAVEL-API-TEST.md +355 -0
- package/docs/MAKE-EXPORT-EXCEL-COMMAND.md +215 -0
- package/docs/README.md +678 -0
- package/docs/STRUCTURE.md +540 -0
- package/docs/starting_point.md +423 -0
- package/index.js +968 -0
- package/package.json +17 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# Excel Export Service Documentation
|
|
2
|
+
|
|
3
|
+
Service ini menyediakan fitur export Excel yang lengkap dengan dukungan multiple sheets, multiple tables, custom styling, chunking untuk data besar, dan informasi export yang detail.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **Multiple Sheets**: Export ke beberapa sheet dalam satu file
|
|
8
|
+
- ✅ **Multiple Tables**: Export beberapa tabel dalam satu sheet
|
|
9
|
+
- ✅ **Custom Styling**: Default styling dan custom styling
|
|
10
|
+
- ✅ **Chunking**: Otomatis memproses data dalam chunk 1000 records
|
|
11
|
+
- ✅ **Export Info**: Header informasi perusahaan, user, tanggal export
|
|
12
|
+
- ✅ **Memory Management**: Manajemen memory dan execution time
|
|
13
|
+
- ✅ **Flexible Headers**: Support custom headers dan column mapping
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
### Environment Variables
|
|
18
|
+
Tambahkan variabel berikut ke `.env`:
|
|
19
|
+
|
|
20
|
+
```env
|
|
21
|
+
# Export Configuration
|
|
22
|
+
EXPORT_AUTHOR_NAME="System Administrator"
|
|
23
|
+
EXPORT_AUTHOR_EMAIL="admin@company.com"
|
|
24
|
+
EXPORT_COMPANY_NAME="Your Company Name"
|
|
25
|
+
EXPORT_COMPANY_ADDRESS="Company Address"
|
|
26
|
+
EXPORT_COMPANY_PHONE="+62-xxx-xxx-xxx"
|
|
27
|
+
EXPORT_COMPANY_WEBSITE="https://company.com"
|
|
28
|
+
EXPORT_CHUNK_SIZE=1000
|
|
29
|
+
EXPORT_MEMORY_LIMIT=512M
|
|
30
|
+
EXPORT_MAX_EXECUTION_TIME=300
|
|
31
|
+
EXPORT_TEMP_DIRECTORY=storage/exports/temp
|
|
32
|
+
EXPORT_INCLUDE_INFO=true
|
|
33
|
+
EXPORT_INCLUDE_TIMESTAMP=true
|
|
34
|
+
EXPORT_INCLUDE_USER_INFO=true
|
|
35
|
+
EXPORT_INCLUDE_COMPANY_INFO=true
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Config File
|
|
39
|
+
File konfigurasi tersedia di `config/export_info.php` dengan pengaturan untuk:
|
|
40
|
+
- Author information
|
|
41
|
+
- Company details
|
|
42
|
+
- Export settings
|
|
43
|
+
- Default styles
|
|
44
|
+
- Format configurations
|
|
45
|
+
|
|
46
|
+
## Basic Usage
|
|
47
|
+
|
|
48
|
+
### 1. Simple Table Export
|
|
49
|
+
|
|
50
|
+
```php
|
|
51
|
+
use App\Exports\SimpleTableExport;
|
|
52
|
+
use App\Models\User;
|
|
53
|
+
|
|
54
|
+
// Basic export
|
|
55
|
+
$query = User::query();
|
|
56
|
+
$headers = ['ID', 'Name', 'Email', 'Created At'];
|
|
57
|
+
|
|
58
|
+
$export = SimpleTableExport::make($query, $headers, 'Users', 'Users Report');
|
|
59
|
+
|
|
60
|
+
// Download file
|
|
61
|
+
return $export->download();
|
|
62
|
+
|
|
63
|
+
// Or save to file
|
|
64
|
+
$filePath = $export->toFile();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 2. Custom Column Mapping
|
|
68
|
+
|
|
69
|
+
```php
|
|
70
|
+
$headers = ['ID', 'Full Name', 'Email', 'Status', 'Join Date'];
|
|
71
|
+
$columnMappings = [
|
|
72
|
+
'id',
|
|
73
|
+
'name',
|
|
74
|
+
'email',
|
|
75
|
+
function ($user) {
|
|
76
|
+
return $user->email_verified_at ? 'Verified' : 'Unverified';
|
|
77
|
+
},
|
|
78
|
+
function ($user) {
|
|
79
|
+
return $user->created_at->format('d/m/Y');
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
$export = SimpleTableExport::make($query, $headers, 'Users')
|
|
84
|
+
->setColumnMappings($columnMappings)
|
|
85
|
+
->setReportTitle('User Status Report');
|
|
86
|
+
|
|
87
|
+
return $export->download();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. Multiple Sheets Export
|
|
91
|
+
|
|
92
|
+
```php
|
|
93
|
+
use App\Exports\UsersPostsExport;
|
|
94
|
+
use App\Models\User;
|
|
95
|
+
use App\Models\Post;
|
|
96
|
+
|
|
97
|
+
// Create export with multiple sheets
|
|
98
|
+
$userQuery = User::whereDate('created_at', '>=', '2024-01-01');
|
|
99
|
+
$postQuery = Post::whereDate('created_at', '>=', '2024-01-01');
|
|
100
|
+
|
|
101
|
+
$export = new UsersPostsExport($userQuery, $postQuery);
|
|
102
|
+
$export->setReportTitle('Q1 2024 Data Report');
|
|
103
|
+
|
|
104
|
+
return $export->download();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Advanced Usage
|
|
108
|
+
|
|
109
|
+
### 1. Using ExcelExportService Directly
|
|
110
|
+
|
|
111
|
+
```php
|
|
112
|
+
use App\Services\ExcelExportService;
|
|
113
|
+
use App\Models\User;
|
|
114
|
+
|
|
115
|
+
$exportService = new ExcelExportService();
|
|
116
|
+
|
|
117
|
+
// Create multiple sheets
|
|
118
|
+
$exportService
|
|
119
|
+
->createSheet('Users', true)
|
|
120
|
+
->createSheet('Summary');
|
|
121
|
+
|
|
122
|
+
// Add data to Users sheet
|
|
123
|
+
$exportService
|
|
124
|
+
->addExportInfo('Users', 'User Data Report')
|
|
125
|
+
->addHeaders('Users', ['ID', 'Name', 'Email', 'Created At'])
|
|
126
|
+
->addData('Users', User::select(['id', 'name', 'email', 'created_at']))
|
|
127
|
+
->autoSizeColumns('Users')
|
|
128
|
+
->freezePane('Users', 'A2');
|
|
129
|
+
|
|
130
|
+
// Add summary to Summary sheet
|
|
131
|
+
$summaryData = [
|
|
132
|
+
[
|
|
133
|
+
'title' => 'User Statistics',
|
|
134
|
+
'headers' => ['Metric', 'Value'],
|
|
135
|
+
'data' => [
|
|
136
|
+
['Total Users', User::count()],
|
|
137
|
+
['Active Users', User::whereNotNull('email_verified_at')->count()],
|
|
138
|
+
['New Users This Month', User::whereMonth('created_at', now()->month)->count()],
|
|
139
|
+
]
|
|
140
|
+
]
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
$exportService
|
|
144
|
+
->addExportInfo('Summary', 'Data Summary')
|
|
145
|
+
->addMultipleTables('Summary', $summaryData)
|
|
146
|
+
->autoSizeColumns('Summary');
|
|
147
|
+
|
|
148
|
+
// Export
|
|
149
|
+
$filename = 'user_report_' . now()->format('Y-m-d_H-i-s') . '.xlsx';
|
|
150
|
+
return $exportService->download($filename);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 2. Custom Styling
|
|
154
|
+
|
|
155
|
+
```php
|
|
156
|
+
// Define custom styles
|
|
157
|
+
$customHeaderStyle = [
|
|
158
|
+
'font' => [
|
|
159
|
+
'bold' => true,
|
|
160
|
+
'size' => 14,
|
|
161
|
+
'color' => ['rgb' => 'FFFFFF'],
|
|
162
|
+
],
|
|
163
|
+
'fill' => [
|
|
164
|
+
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
|
|
165
|
+
'startColor' => ['rgb' => '4CAF50'],
|
|
166
|
+
],
|
|
167
|
+
'borders' => [
|
|
168
|
+
'allBorders' => [
|
|
169
|
+
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THICK,
|
|
170
|
+
'color' => ['rgb' => '000000'],
|
|
171
|
+
],
|
|
172
|
+
],
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
$customBodyStyle = [
|
|
176
|
+
'font' => ['size' => 11],
|
|
177
|
+
'borders' => [
|
|
178
|
+
'allBorders' => [
|
|
179
|
+
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
180
|
+
'color' => ['rgb' => 'DDDDDD'],
|
|
181
|
+
],
|
|
182
|
+
],
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
// Apply to SimpleTableExport
|
|
186
|
+
$export = SimpleTableExport::make($query, $headers, 'Custom Report')
|
|
187
|
+
->setCustomStyles($customBodyStyle);
|
|
188
|
+
|
|
189
|
+
// Or apply directly to service
|
|
190
|
+
$exportService
|
|
191
|
+
->addHeaders('Sheet1', $headers)
|
|
192
|
+
->applyStyle($worksheet, 'A1:D1', $customHeaderStyle)
|
|
193
|
+
->addData('Sheet1', $data, 1, $customBodyStyle);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 3. Column Width and Formatting
|
|
197
|
+
|
|
198
|
+
```php
|
|
199
|
+
$export = SimpleTableExport::make($query, $headers, 'Formatted Report')
|
|
200
|
+
->setColumnWidths([
|
|
201
|
+
'A' => 20, // ID column
|
|
202
|
+
'B' => 30, // Name column
|
|
203
|
+
'C' => 35, // Email column
|
|
204
|
+
'D' => 25 // Date column
|
|
205
|
+
]);
|
|
206
|
+
|
|
207
|
+
// Or use auto-size (default behavior)
|
|
208
|
+
$export->autoSizeColumns('Sheet1');
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## API Endpoints
|
|
212
|
+
|
|
213
|
+
### Available Endpoints
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
GET /api/v1/export/users-posts // Export users and posts
|
|
217
|
+
GET /api/v1/export/users // Export users only
|
|
218
|
+
GET /api/v1/export/custom-styled // Custom styled example
|
|
219
|
+
GET /api/v1/export/multiple-tables // Multiple tables example
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Query Parameters
|
|
223
|
+
|
|
224
|
+
- `download=true/false` - Download file or return file path (default: true)
|
|
225
|
+
- `date_from` - Filter data from date (YYYY-MM-DD)
|
|
226
|
+
- `date_to` - Filter data to date (YYYY-MM-DD)
|
|
227
|
+
- `search` - Search term for filtering
|
|
228
|
+
- `verified=true/false` - Filter verified/unverified users
|
|
229
|
+
|
|
230
|
+
### Example API Calls
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# Download users and posts export
|
|
234
|
+
curl -H "Authorization: Bearer {token}" \
|
|
235
|
+
"http://localhost:8000/api/v1/export/users-posts?download=true"
|
|
236
|
+
|
|
237
|
+
# Get file path for users export with date filter
|
|
238
|
+
curl -H "Authorization: Bearer {token}" \
|
|
239
|
+
"http://localhost:8000/api/v1/export/users?download=false&date_from=2024-01-01&date_to=2024-12-31"
|
|
240
|
+
|
|
241
|
+
# Export verified users only
|
|
242
|
+
curl -H "Authorization: Bearer {token}" \
|
|
243
|
+
"http://localhost:8000/api/v1/export/users?verified=true&search=john"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Creating Custom Export Classes
|
|
247
|
+
|
|
248
|
+
### 1. Extend BaseExport
|
|
249
|
+
|
|
250
|
+
```php
|
|
251
|
+
<?php
|
|
252
|
+
|
|
253
|
+
namespace App\Exports;
|
|
254
|
+
|
|
255
|
+
class CustomExport extends BaseExport
|
|
256
|
+
{
|
|
257
|
+
protected $data;
|
|
258
|
+
protected $options;
|
|
259
|
+
|
|
260
|
+
public function __construct($data, array $options = [])
|
|
261
|
+
{
|
|
262
|
+
parent::__construct();
|
|
263
|
+
|
|
264
|
+
$this->data = $data;
|
|
265
|
+
$this->options = $options;
|
|
266
|
+
$this->reportTitle = $options['title'] ?? 'Custom Report';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
public function export()
|
|
270
|
+
{
|
|
271
|
+
$this->exportService
|
|
272
|
+
->createSheet('Data', true)
|
|
273
|
+
->addExportInfo('Data', $this->reportTitle);
|
|
274
|
+
|
|
275
|
+
// Your custom logic here
|
|
276
|
+
$headers = $this->options['headers'] ?? ['Column 1', 'Column 2'];
|
|
277
|
+
|
|
278
|
+
$this->exportService
|
|
279
|
+
->addHeaders('Data', $headers)
|
|
280
|
+
->addData('Data', $this->data)
|
|
281
|
+
->autoSizeColumns('Data')
|
|
282
|
+
->freezePane('Data', 'A2');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 2. Use the Custom Export
|
|
288
|
+
|
|
289
|
+
```php
|
|
290
|
+
$data = collect([
|
|
291
|
+
['Value 1', 'Value 2'],
|
|
292
|
+
['Value 3', 'Value 4'],
|
|
293
|
+
]);
|
|
294
|
+
|
|
295
|
+
$export = new CustomExport($data, [
|
|
296
|
+
'title' => 'My Custom Report',
|
|
297
|
+
'headers' => ['Column A', 'Column B']
|
|
298
|
+
]);
|
|
299
|
+
|
|
300
|
+
return $export->download();
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Performance Tips
|
|
304
|
+
|
|
305
|
+
1. **Use Chunking**: Service automatically chunks data per 1000 records
|
|
306
|
+
2. **Memory Limit**: Adjust `EXPORT_MEMORY_LIMIT` in .env for large datasets
|
|
307
|
+
3. **Execution Time**: Set `EXPORT_MAX_EXECUTION_TIME` appropriately
|
|
308
|
+
4. **Selective Fields**: Only select required columns from database
|
|
309
|
+
|
|
310
|
+
```php
|
|
311
|
+
// Good - select specific columns
|
|
312
|
+
$query = User::select(['id', 'name', 'email', 'created_at']);
|
|
313
|
+
|
|
314
|
+
// Avoid - select all columns
|
|
315
|
+
$query = User::all();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Error Handling
|
|
319
|
+
|
|
320
|
+
Service includes built-in error handling. Wrap calls in try-catch for custom error handling:
|
|
321
|
+
|
|
322
|
+
```php
|
|
323
|
+
try {
|
|
324
|
+
$export = new UsersPostsExport();
|
|
325
|
+
return $export->download();
|
|
326
|
+
} catch (\Exception $e) {
|
|
327
|
+
return response()->json([
|
|
328
|
+
'error' => 'Export failed: ' . $e->getMessage()
|
|
329
|
+
], 500);
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Troubleshooting
|
|
334
|
+
|
|
335
|
+
### Common Issues
|
|
336
|
+
|
|
337
|
+
1. **Memory Limit Exceeded**: Increase `EXPORT_MEMORY_LIMIT`
|
|
338
|
+
2. **Execution Timeout**: Increase `EXPORT_MAX_EXECUTION_TIME`
|
|
339
|
+
3. **File Not Found**: Check `EXPORT_TEMP_DIRECTORY` permissions
|
|
340
|
+
4. **Style Not Applied**: Verify PhpSpreadsheet style array format
|
|
341
|
+
|
|
342
|
+
### Debug Mode
|
|
343
|
+
|
|
344
|
+
Enable debug logging:
|
|
345
|
+
|
|
346
|
+
```php
|
|
347
|
+
// In export class
|
|
348
|
+
\Log::info('Export started', ['query_count' => $query->count()]);
|
|
349
|
+
```
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# Export Data Providers Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Data Providers adalah komponen yang memisahkan logika data (rawData, headers, dataMapper) dari controller. Ini membuat code lebih modular, testable, dan mudah di-maintain.
|
|
5
|
+
|
|
6
|
+
## Structure
|
|
7
|
+
```
|
|
8
|
+
app/Exports/DataProviders/
|
|
9
|
+
├── ExportDataProviderInterface.php (Interface)
|
|
10
|
+
├── FlexibleTemplateDataProvider.php
|
|
11
|
+
├── MultiSheetTemplateDataProvider.php
|
|
12
|
+
├── MultiTableTemplateDataProvider.php
|
|
13
|
+
├── UserExportDataProvider.php
|
|
14
|
+
├── ExternalDataProvider.php
|
|
15
|
+
└── ProductExportDataProvider.php
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Interface Contract
|
|
19
|
+
Setiap Data Provider harus implement `ExportDataProviderInterface`:
|
|
20
|
+
|
|
21
|
+
```php
|
|
22
|
+
interface ExportDataProviderInterface
|
|
23
|
+
{
|
|
24
|
+
public function getRawData($filters = null): array;
|
|
25
|
+
public function getHeaders(): array;
|
|
26
|
+
public function getDataMapper(): array;
|
|
27
|
+
public function getOptions(): array;
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage in Controller
|
|
32
|
+
|
|
33
|
+
### Before (Dirty Controller)
|
|
34
|
+
```php
|
|
35
|
+
public function exportFlexibleTemplate(Request $request)
|
|
36
|
+
{
|
|
37
|
+
// 50+ lines of hard-coded data, headers, mappers
|
|
38
|
+
$rawData = [/* lots of data */];
|
|
39
|
+
$headers = [/* headers */];
|
|
40
|
+
$dataMapper = [/* mappers */];
|
|
41
|
+
// ...
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### After (Clean Controller)
|
|
46
|
+
```php
|
|
47
|
+
public function exportFlexibleTemplate(Request $request)
|
|
48
|
+
{
|
|
49
|
+
$provider = new FlexibleTemplateDataProvider();
|
|
50
|
+
|
|
51
|
+
$rawData = $provider->getRawData();
|
|
52
|
+
$headers = $provider->getHeaders();
|
|
53
|
+
$dataMapper = $provider->getDataMapper();
|
|
54
|
+
$options = $provider->getOptions();
|
|
55
|
+
|
|
56
|
+
$export = FlexibleExport::create($rawData, $headers, array_merge($options, [
|
|
57
|
+
'data_mapper' => $dataMapper
|
|
58
|
+
]));
|
|
59
|
+
|
|
60
|
+
return $request->boolean('download', true) ? $export->download() : /* JSON response */;
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Benefits
|
|
65
|
+
|
|
66
|
+
### 1. Separation of Concerns
|
|
67
|
+
- Controller hanya handle HTTP layer
|
|
68
|
+
- Data Provider handle data preparation
|
|
69
|
+
- Export Templates handle Excel generation
|
|
70
|
+
|
|
71
|
+
### 2. Reusability
|
|
72
|
+
Data providers bisa digunakan di berbagai controller atau command:
|
|
73
|
+
```php
|
|
74
|
+
// Di Controller
|
|
75
|
+
$provider = new UserExportDataProvider($request);
|
|
76
|
+
|
|
77
|
+
// Di Artisan Command
|
|
78
|
+
$provider = new UserExportDataProvider();
|
|
79
|
+
|
|
80
|
+
// Di Job Queue
|
|
81
|
+
$provider = new UserExportDataProvider();
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Testability
|
|
85
|
+
```php
|
|
86
|
+
class UserExportDataProviderTest extends TestCase
|
|
87
|
+
{
|
|
88
|
+
public function test_get_headers()
|
|
89
|
+
{
|
|
90
|
+
$provider = new UserExportDataProvider(new Request());
|
|
91
|
+
$headers = $provider->getHeaders();
|
|
92
|
+
|
|
93
|
+
$this->assertEquals(['ID', 'Full Name', 'Email Address', ...], $headers);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 4. Maintainability
|
|
99
|
+
Ubah data mapping tanpa touch controller:
|
|
100
|
+
```php
|
|
101
|
+
// UserExportDataProvider.php
|
|
102
|
+
public function getDataMapper(): array
|
|
103
|
+
{
|
|
104
|
+
return [
|
|
105
|
+
'id',
|
|
106
|
+
'name',
|
|
107
|
+
'email',
|
|
108
|
+
// Add new formatter without changing controller
|
|
109
|
+
function ($user) {
|
|
110
|
+
return $user['premium'] ? 'Premium ⭐' : 'Regular';
|
|
111
|
+
}
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Provider Types
|
|
117
|
+
|
|
118
|
+
### 1. Simple Data Provider
|
|
119
|
+
Untuk static/sample data:
|
|
120
|
+
```php
|
|
121
|
+
class FlexibleTemplateDataProvider implements ExportDataProviderInterface
|
|
122
|
+
{
|
|
123
|
+
public function getRawData($filters = null): array
|
|
124
|
+
{
|
|
125
|
+
return [/* static sample data */];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 2. Model-based Data Provider
|
|
131
|
+
Untuk data dari database:
|
|
132
|
+
```php
|
|
133
|
+
class UserExportDataProvider implements ExportDataProviderInterface
|
|
134
|
+
{
|
|
135
|
+
private Request $request;
|
|
136
|
+
|
|
137
|
+
public function __construct(Request $request)
|
|
138
|
+
{
|
|
139
|
+
$this->request = $request;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public function getRawData($filters = null): array
|
|
143
|
+
{
|
|
144
|
+
$query = User::query();
|
|
145
|
+
// Apply request filters
|
|
146
|
+
return $query->get()->toArray();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 3. Complex Data Provider
|
|
152
|
+
Untuk multi-sheet/multi-table:
|
|
153
|
+
```php
|
|
154
|
+
class MultiSheetTemplateDataProvider implements ExportDataProviderInterface
|
|
155
|
+
{
|
|
156
|
+
// Implement helper methods
|
|
157
|
+
public function getFormattedSheets(): array
|
|
158
|
+
{
|
|
159
|
+
// Return ready-to-use sheets configuration
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 4. External API Data Provider
|
|
165
|
+
Untuk data dari API external:
|
|
166
|
+
```php
|
|
167
|
+
class ExternalDataProvider implements ExportDataProviderInterface
|
|
168
|
+
{
|
|
169
|
+
public function getRawData($filters = null): array
|
|
170
|
+
{
|
|
171
|
+
// Fetch from external API
|
|
172
|
+
// Transform data
|
|
173
|
+
return $transformedData;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Creating New Data Provider
|
|
179
|
+
|
|
180
|
+
### Step 1: Create Provider Class
|
|
181
|
+
```php
|
|
182
|
+
<?php
|
|
183
|
+
namespace App\Exports\DataProviders;
|
|
184
|
+
|
|
185
|
+
class NewExportDataProvider implements ExportDataProviderInterface
|
|
186
|
+
{
|
|
187
|
+
public function getRawData($filters = null): array
|
|
188
|
+
{
|
|
189
|
+
// Your data logic here
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public function getHeaders(): array
|
|
194
|
+
{
|
|
195
|
+
return ['Column 1', 'Column 2'];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public function getDataMapper(): array
|
|
199
|
+
{
|
|
200
|
+
return [
|
|
201
|
+
'field1',
|
|
202
|
+
function ($item) {
|
|
203
|
+
return formatValue($item['field2']);
|
|
204
|
+
}
|
|
205
|
+
];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
public function getOptions(): array
|
|
209
|
+
{
|
|
210
|
+
return [
|
|
211
|
+
'sheet_title' => 'My Export',
|
|
212
|
+
'report_title' => 'My Report',
|
|
213
|
+
'column_widths' => ['A' => 15, 'B' => 20],
|
|
214
|
+
'freeze_pane' => 'A2'
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Step 2: Use in Controller
|
|
221
|
+
```php
|
|
222
|
+
public function exportNewTemplate(Request $request)
|
|
223
|
+
{
|
|
224
|
+
try {
|
|
225
|
+
$provider = new NewExportDataProvider();
|
|
226
|
+
|
|
227
|
+
$rawData = $provider->getRawData();
|
|
228
|
+
$headers = $provider->getHeaders();
|
|
229
|
+
$dataMapper = $provider->getDataMapper();
|
|
230
|
+
$options = $provider->getOptions();
|
|
231
|
+
|
|
232
|
+
$export = FlexibleExport::create($rawData, $headers, array_merge($options, [
|
|
233
|
+
'data_mapper' => $dataMapper
|
|
234
|
+
]));
|
|
235
|
+
|
|
236
|
+
return $request->boolean('download', true) ? $export->download() : /* JSON response */;
|
|
237
|
+
|
|
238
|
+
} catch (\Exception $e) {
|
|
239
|
+
return response()->json([
|
|
240
|
+
'success' => false,
|
|
241
|
+
'message' => 'Export failed: ' . $e->getMessage()
|
|
242
|
+
], 500);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Advanced Features
|
|
248
|
+
|
|
249
|
+
### Dynamic Filtering
|
|
250
|
+
```php
|
|
251
|
+
public function getRawData($filters = null): array
|
|
252
|
+
{
|
|
253
|
+
$query = Model::query();
|
|
254
|
+
|
|
255
|
+
if ($filters) {
|
|
256
|
+
foreach ($filters as $key => $value) {
|
|
257
|
+
$query->where($key, $value);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return $query->get()->toArray();
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Conditional Data Mapping
|
|
266
|
+
```php
|
|
267
|
+
public function getDataMapper(): array
|
|
268
|
+
{
|
|
269
|
+
$mappers = ['id', 'name', 'email'];
|
|
270
|
+
|
|
271
|
+
// Add conditional mappers
|
|
272
|
+
if (auth()->user()->hasPermission('view_sensitive_data')) {
|
|
273
|
+
$mappers[] = function ($item) {
|
|
274
|
+
return $item['social_security_number'];
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return $mappers;
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Caching Support
|
|
283
|
+
```php
|
|
284
|
+
public function getRawData($filters = null): array
|
|
285
|
+
{
|
|
286
|
+
$cacheKey = 'export_data_' . md5(serialize($filters));
|
|
287
|
+
|
|
288
|
+
return Cache::remember($cacheKey, 300, function () use ($filters) {
|
|
289
|
+
return Model::query()->where($filters)->get()->toArray();
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Testing Examples
|
|
295
|
+
|
|
296
|
+
```php
|
|
297
|
+
class UserExportDataProviderTest extends TestCase
|
|
298
|
+
{
|
|
299
|
+
public function test_headers_contain_required_columns()
|
|
300
|
+
{
|
|
301
|
+
$provider = new UserExportDataProvider(new Request());
|
|
302
|
+
$headers = $provider->getHeaders();
|
|
303
|
+
|
|
304
|
+
$this->assertContains('ID', $headers);
|
|
305
|
+
$this->assertContains('Full Name', $headers);
|
|
306
|
+
$this->assertContains('Email Address', $headers);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
public function test_data_mapper_formats_correctly()
|
|
310
|
+
{
|
|
311
|
+
$provider = new UserExportDataProvider(new Request());
|
|
312
|
+
$mapper = $provider->getDataMapper();
|
|
313
|
+
|
|
314
|
+
$testData = ['email_verified_at' => '2024-01-15'];
|
|
315
|
+
$result = $mapper[3]($testData); // Verification status mapper
|
|
316
|
+
|
|
317
|
+
$this->assertEquals('Verified ✓', $result);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Best Practices
|
|
323
|
+
|
|
324
|
+
1. **Single Responsibility**: Satu provider untuk satu jenis export
|
|
325
|
+
2. **Consistent Naming**: `[Entity]ExportDataProvider` atau `[Purpose]DataProvider`
|
|
326
|
+
3. **Documentation**: Comment complex data mappers
|
|
327
|
+
4. **Error Handling**: Handle missing/invalid data gracefully
|
|
328
|
+
5. **Performance**: Use eager loading, chunking untuk data besar
|
|
329
|
+
6. **Security**: Validate permissions dalam getRawData()
|
|
330
|
+
|
|
331
|
+
## Migration Path
|
|
332
|
+
|
|
333
|
+
1. Identify hard-coded data in controllers
|
|
334
|
+
2. Create corresponding data provider
|
|
335
|
+
3. Move data logic to provider
|
|
336
|
+
4. Update controller to use provider
|
|
337
|
+
5. Test functionality
|
|
338
|
+
6. Remove old hard-coded data
|
|
339
|
+
|
|
340
|
+
Semua export functions telah berhasil di-refactor dan tested! 🎉
|