Skip to main content

English Version

1. Core Concepts

This system is designed to be a flexible and extensible pipeline for converting documents from various source formats (like Markdown or HTML) into target formats (like PDF or DOCX). The architecture is built on these key principles:
  • DocumentConverter Service: This is the central orchestrator of the pipeline. It provides a fluent interface that makes the conversion process readable and easy to manage. It doesn’t perform conversions itself; it delegates tasks to the appropriate drivers.
  • Input Drivers: An Input Driver’s job is to take raw content from a source file (e.g., a .md or .html file) and prepare it for rendering. This typically involves replacing placeholders with data and wrapping the content in a master Blade layout.
  • Output Drivers: An Output Driver’s job is to take the final, fully-rendered HTML (after Blade has processed it) and convert it into the target format’s binary content (e.g., the binary data of a PDF or DOCX file).
  • Blade as the Intermediate Format: All conversions pass through a common intermediate step: a Blade view. This allows us to centralize styling (CSS) and document structure (headers, footers) in a single master layout file, ensuring consistency across all generated documents.
  • Laravel Filesystem Integration: The final step of saving the document is handled by Laravel’s Storage facade, allowing you to save the output to any configured disk, including local storage, S3, or an S3-compatible service like MinIO.

2. Configuration

Before using the pipeline, ensure the following are configured: A. System & PHP Dependencies: Make sure you have installed the required system tools and Composer packages.
  • System Tool: weasyprint (for PDF generation).
  • Composer Packages: phpoffice/phpword, rockett/weasyprint, league/flysystem-aws-s3-v3.
B. Environment Variables (.env) To save files to an S3-compatible disk like MinIO, add the credentials to your .env file.
MINIO_ACCESS_KEY_ID=your-minio-access-key
MINIO_SECRET_ACCESS_KEY=your-minio-secret-key
MINIO_REGION=us-east-1
MINIO_BUCKET=documents
MINIO_ENDPOINT="http://127.0.0.1:9000"
MINIO_USE_PATH_STYLE_ENDPOINT=true
C. Filesystem Disk (config/filesystems.php) Define the minio disk so Laravel’s Storage facade knows how to connect to it.
'disks' => [
    // ...
    'minio' => [
        'driver' => 's3',
        'key' => env('MINIO_ACCESS_KEY_ID'),
        'secret' => env('MINIO_SECRET_ACCESS_KEY'),
        // ... all other S3 settings
    ],
],
D. Driver Mapping (config/documents.php) This is the core configuration file for the pipeline. It maps file extensions to the driver classes that should handle them.
<?php
// config/documents.php

use App\Services\DocumentConversion\Drivers\Input;
use App\Services\DocumentConversion\Drivers\Output;

return [
    'input_drivers' => [
        'md'   => Input\MarkdownInputDriver::class,
        'html' => Input\HtmlInputDriver::class,
        'htm'  => Input\HtmlInputDriver::class,
    ],
    'output_drivers' => [
        'pdf'  => Output\WeasyPrintOutputDriver::class,
        'docx' => Output\DocxOutputDriver::class,
    ],
];

3. Usage Guide

You can use the pipeline via the provided Artisan command or programmatically within your application. A. Using the Artisan Command (convert:document) This is the primary way to perform conversions from the command line.
  • Convert a Markdown file to a PDF on MinIO:
php artisan convert:document invoices/INV-001.pdf --input=storage/app/templates/invoice.md --disk=minio --data='{"customer_name":"Acme Corp"}'
  • Convert an HTML file to a DOCX on the local public disk:
php artisan convert:document reports/quarterly.docx --input=storage/app/templates/report.html --disk=public
  • Convert directly from a Blade view to a PDF: (Assumes you have resources/views/documents/receipt.blade.php)
php artisan convert:document receipts/R-552.pdf --view=documents.receipt --disk=minio --data='{"amount":"$99.00"}'
  • Specify a custom layout for a file-based conversion:
php artisan convert:document newsletter.pdf --input=content.md --disk=public --layout=layouts.newsletter
B. Programmatic Usage (e.g., in a Controller) You can also use the DocumentConverter service directly in your code for dynamic document generation.
use App\Services\DocumentConversion\DocumentConverter;
use App\Models\Order;

class OrderController extends Controller
{
    public function downloadInvoice(Order $order)
    {
        $data = [
            'order_id' => $order->id,
            'customer_name' => $order->customer->name,
            'items' => $order->items,
        ];

        $filePath = "invoices/{$order->id}.pdf";

        // Use the service to convert a Blade view
        DocumentConverter::fromBlade('invoices.template')
            ->withData($data)
            ->saveTo('minio', $filePath);

        // Now you can redirect the user to the file's URL
        return redirect()->away(Storage::disk('minio')->url($filePath));
    }
}

4. Extending the Pipeline

A. Creating a New Input Driver
  1. Create a new class in app/Services/DocumentConversion/Drivers/Input that implements InputDriverInterface.
  2. Implement the process() method. It must accept raw content and return a Blade-compatible string that extends a layout.
  3. Register your new driver in config/documents.php with the file extension it handles.
B. Creating a New Output Driver
  1. Create a new class in app/Services/DocumentConversion/Drivers/Output that implements OutputDriverInterface.
  2. Implement the render() method. It must accept the final HTML and return the raw binary content of the converted file as a string.
  3. Register your new driver in config/documents.php with its output file extension.

5. Testing

It’s crucial to test your document generation logic. Use Laravel’s Storage::fake() to prevent actual files from being written to disk during tests. Here is an example using Pest/PHPUnit:
use Illuminate\Support\Facades\Storage;
use App\Services\DocumentConversion\DocumentConverter;

it('can convert a markdown file to a pdf', function () {
    // 1. Setup: Fake the storage disk
    Storage::fake('minio');

    // 2. Arrange: Create a fake input file
    $markdownContent = '# Hello {{ name }}';
    Storage::fake('local')->put('test.md', $markdownContent);
    $inputPath = Storage::disk('local')->path('test.md');

    $data = ['name' => 'World'];
    $outputPath = 'output/test.pdf';

    // 3. Act: Run the conversion
    DocumentConverter::from($inputPath)
        ->withData($data)
        ->saveTo('minio', $outputPath);

    // 4. Assert: Check that the file was created on the fake disk
    Storage::disk('minio')->assertExists($outputPath);
});

Addendum 1: Advanced Spreadsheet Conversion

A.1 Using Spreadsheets as Input

The pipeline can read data from .csv and .xlsx files and render it as an HTML <table> within a target document (like a PDF or DOCX). This is ideal for generating reports from spreadsheet data.

Concept

When a spreadsheet file is used as input, the corresponding Input Driver performs the following steps:
  1. Parses the .csv or .xlsx file using a dedicated spreadsheet library.
  2. Reads all the rows and cells from the first sheet.
  3. Transforms this data into an HTML <table> string.
  4. Wraps this HTML table string within the standard Blade layout directives (@extends, @section).
  5. Passes this Blade string to the renderer, which then flows through the rest of the pipeline to the chosen output format.

Available Engines

The system supports multiple spreadsheet engines, configurable in config/documents.php. You can choose the one that best fits your needs.
  1. MaatwebsiteInputDriver: (Default) A user-friendly, feature-rich driver using the popular maatwebsite/excel package. Great for general use.
  2. OpenSpoutInputDriver: A high-performance, low-memory driver using the openspout/openspout package. Recommended for very large files.
  3. PhpSpreadsheetInputDriver: A powerful driver using the underlying phpoffice/phpspreadsheet library. Offers maximum control and feature access.

Configuration

To switch engines, simply edit config/documents.php and point the csv and xlsx keys to your desired driver class.
// config/documents.php
'input_drivers' => [
    // ...
    // --- To use OpenSpout instead of the default Maatwebsite ---
    'csv'  => \App\Services\DocumentConversion\Drivers\Input\OpenSpoutInputDriver::class,
    'xlsx' => \App\Services\DocumentConversion\Drivers\Input\OpenSpoutInputDriver::class,
],

Usage

The command is the same regardless of the chosen engine.
# Convert a CSV file into a PDF report
php artisan convert:document reports/sales-summary.pdf --input=data/sales.csv --disk=public

# Convert an XLSX file into a DOCX document
php artisan convert:document reports/inventory.docx --input=data/inventory.xlsx --disk=public

A.2 Generating Spreadsheets as Output

The pipeline can also convert a source document (like Markdown or HTML) into an .xlsx file. This is useful for exporting structured and unstructured content into a spreadsheet format.

Concept

This is a more advanced conversion. When .xlsx is the target format, the Output Driver performs a unique process:
  1. It receives the final, fully-rendered HTML from the Blade engine.
  2. It parses the HTML DOM structure.
  3. When it encounters a <table> element, it translates the table’s rows (<tr>) and cells (<th>, <td>) directly into spreadsheet rows and cells.
  4. When it encounters any other block-level element (<h1>, <p>, <ul>, etc.), it extracts the element’s text content and places it into a new spreadsheet row in the first column.
  5. This preserves both the structured data and the textual context of the original document.

Available Engines

Like with input, you have a choice of engines for generating XLSX files.
  1. MaatwebsiteOutputDriver: (Default) Uses maatwebsite/excel to easily build the spreadsheet from a PHP array. Very convenient and reliable.
  2. OpenSpoutOutputDriver: Uses openspout/openspout’s streaming writer. Excellent for generating extremely large XLSX files without hitting memory limits.
  3. PhpSpreadsheetOutputDriver: Uses phpoffice/phpspreadsheet to build the document in memory. Offers deep control over cell styling, formulas, and other advanced features.

Configuration

To switch engines, edit the xlsx key in the output_drivers section of config/documents.php.
// config/documents.php
'output_drivers' => [
    // ...
    // --- To use PhpSpreadsheet instead of the default Maatwebsite ---
    'xlsx' => \App\Services\DocumentConversion\Drivers\Output\PhpSpreadsheetOutputDriver::class,
],

Usage

# Convert a Markdown file (containing text and a table) into an XLSX file
php artisan convert:document exports/invoice-data.xlsx --input=storage/app/templates/invoice.md --disk=minio
The resulting XLSX file will contain the text from the Markdown file in Column A, with the table’s data structured correctly across multiple columns.

Addendum 2: Advanced XLSX Generation with Templates

A.2.1 Concept

While the standard output drivers are excellent for converting a document’s content into spreadsheet rows, the templating system provides a higher level of control over the final document’s layout and presentation. The core idea is to use a pre-designed .xlsx file as a template. This template can contain headers, footers, logos, static text, and pre-styled cells. The pipeline then injects dynamic data and content into this template. This process is handled by a new, specialized driver: TemplatedXlsxOutputDriver. This driver is powered by the phpoffice/phpspreadsheet library, as it’s the only one capable of both reading an existing spreadsheet and modifying it.

A.2.2 Creating the XLSX Template

To use this feature, you must first create a template .xlsx file (e.g., storage/app/templates/report-template.xlsx). This file uses two types of special markers:
  1. Global Placeholders: For single data points like a title or a date, you can place Blade-style placeholders directly into any cell. The driver will find and replace these.
  • Syntax: {{ $variable_name }} or {{ $user.name }}
  • Example: A cell containing Report for: {{ $customer_name }}
  1. Content Start Marker: You must designate a single cell where the main, dynamic HTML content will begin to be inserted. All content will flow downwards from this point.
  • Marker: {{CONTENT_START}}
Example Template (report-template.xlsx):
ABCD
1{{ $report_title }}Company Logo Here
2Generated On:{{ $generated_on }}
3
4Transaction Details
5{{CONTENT_START}}

A.2.3 HTML to Cell Style Mapping

When the TemplatedXlsxOutputDriver processes the HTML content, it applies basic cell styling based on the HTML tags it encounters. This adds a typographic hierarchy to your report.
  • <h1>, <h2>, <h3>: Text is made bold with decreasing font sizes.
  • <b>, <strong>: Text is made bold.
  • <i>, <em>: Text is made italic.
  • <table>: The driver recognizes HTML tables and correctly maps <tr>, <th>, and <td> to spreadsheet rows and cells, preserving the tabular structure.

A.2.4 Configuration

To enable this feature, ensure the TemplatedXlsxOutputDriver is set as the handler for the .xlsx extension in your config/documents.php file.
// config/documents.php
'output_drivers' => [
    // ...
    // This driver is now the default for creating rich, templated reports.
    'xlsx' => \App\Services\DocumentConversion\Drivers\Output\TemplatedXlsxOutputDriver::class,

    // You can keep old drivers for simpler, non-templated exports under a different key
    'xlsx_simple' => \App\Services\DocumentConversion\Drivers\Output\MaatwebsiteOutputDriver::class,
],

A.2.5 Usage

You activate the templating feature by specifying the path to your XLSX template file. A. Using the Artisan Command Use the new --output-template option.
php artisan convert:document reports/MonthlyReport.xlsx \
--input=storage/app/templates/invoice.md \
--disk=public \
--output-template=storage/app/templates/report-template.xlsx \
--data='{"report_title":"Monthly Sales","generated_on":"2023-11-15","customer_name":"Global Corp"}'
B. Programmatic Usage Use the new ->usingOutputTemplate() fluent method on the DocumentConverter service.
use App\Services\DocumentConversion\DocumentConverter;

// ... inside a controller or service
$data = [
    'report_title' => 'Monthly Sales',
    'generated_on' => now()->toDateString(),
    'customer_name' => 'Global Corp',
];

DocumentConverter::fromBlade('reports.monthly_sales_content')
    ->withData($data)
    ->usingOutputTemplate(storage_path('app/templates/report-template.xlsx'))
    ->saveTo('minio', 'reports/MonthlyReport.xlsx');
The system will now produce a fully formatted XLSX file based on your template, filled with the dynamic data and styled content.

Versi Bahasa Indonesia

1. Konsep Inti

Sistem ini dirancang untuk menjadi pipeline (alur proses) yang fleksibel dan dapat diperluas untuk mengonversi dokumen dari berbagai format sumber (seperti Markdown atau HTML) ke format target (seperti PDF atau DOCX). Arsitekturnya dibangun di atas prinsip-prinsip utama berikut:
  • Service DocumentConverter: Ini adalah orkestrator pusat dari pipeline. Ia menyediakan fluent interface yang membuat proses konversi mudah dibaca dan dikelola. Service ini tidak melakukan konversi secara langsung; ia mendelegasikan tugas ke driver yang sesuai.
  • Input Driver: Tugas Input Driver adalah mengambil konten mentah dari file sumber (misalnya, file .md atau .html) dan menyiapkannya untuk di-render. Ini biasanya melibatkan penggantian placeholder dengan data dan membungkus konten dalam layout master Blade.
  • Output Driver: Tugas Output Driver adalah mengambil HTML final yang sudah di-render (setelah diproses oleh Blade) dan mengubahnya menjadi konten biner dari format target (misalnya, data biner dari file PDF atau DOCX).
  • Blade sebagai Format Perantara: Semua konversi melewati langkah perantara yang sama: view Blade. Ini memungkinkan kita untuk memusatkan styling (CSS) dan struktur dokumen (header, footer) dalam satu file layout master, memastikan konsistensi di semua dokumen yang dihasilkan.
  • Integrasi Filesystem Laravel: Langkah terakhir untuk menyimpan dokumen ditangani oleh Storage facade dari Laravel, memungkinkan Anda menyimpan output ke disk apa pun yang telah dikonfigurasi, termasuk penyimpanan lokal, S3, atau layanan yang kompatibel dengan S3 seperti MinIO.

2. Konfigurasi

Sebelum menggunakan pipeline, pastikan hal-hal berikut telah dikonfigurasi: A. Dependensi Sistem & PHP: Pastikan Anda telah menginstal perangkat lunak sistem dan paket Composer yang diperlukan.
  • Perangkat Lunak Sistem: weasyprint (untuk pembuatan PDF).
  • Paket Composer: phpoffice/phpword, rockett/weasyprint, league/flysystem-aws-s3-v3.
B. Variabel Environment (.env) Untuk menyimpan file ke disk yang kompatibel dengan S3 seperti MinIO, tambahkan kredensial ke file .env Anda.
MINIO_ACCESS_KEY_ID=kunci-akses-minio-anda
MINIO_SECRET_ACCESS_KEY=kunci-rahasia-minio-anda
MINIO_REGION=us-east-1
MINIO_BUCKET=documents
MINIO_ENDPOINT="http://127.0.0.1:9000"
MINIO_USE_PATH_STYLE_ENDPOINT=true
C. Disk Filesystem (config/filesystems.php) Definisikan disk minio agar Storage facade Laravel tahu cara terhubung dengannya.
'disks' => [
    // ...
    'minio' => [
        'driver' => 's3',
        'key' => env('MINIO_ACCESS_KEY_ID'),
        'secret' => env('MINIO_SECRET_ACCESS_KEY'),
        // ... semua pengaturan S3 lainnya
    ],
],
D. Pemetaan Driver (config/documents.php) Ini adalah file konfigurasi inti untuk pipeline. File ini memetakan ekstensi file ke kelas driver yang harus menanganinya.
<?php
// config/documents.php

use App\Services\DocumentConversion\Drivers\Input;
use App\Services\DocumentConversion\Drivers\Output;

return [
    'input_drivers' => [
        'md'   => Input\MarkdownInputDriver::class,
        'html' => Input\HtmlInputDriver::class,
        'htm'  => Input\HtmlInputDriver::class,
    ],
    'output_drivers' => [
        'pdf'  => Output\WeasyPrintOutputDriver::class,
        'docx' => Output\DocxOutputDriver::class,
    ],
];

3. Panduan Penggunaan

Anda dapat menggunakan pipeline melalui perintah Artisan yang disediakan atau secara terprogram di dalam aplikasi Anda. A. Menggunakan Perintah Artisan (convert:document) Ini adalah cara utama untuk melakukan konversi dari baris perintah.
  • Mengonversi file Markdown ke PDF di MinIO:
php artisan convert:document invoices/INV-001.pdf --input=storage/app/templates/invoice.md --disk=minio --data='{"customer_name":"PT Sejahtera"}'
  • Mengonversi file HTML ke DOCX di disk public lokal:
php artisan convert:document reports/quarterly.docx --input=storage/app/templates/report.html --disk=public
  • Mengonversi langsung dari view Blade ke PDF: (Asumsikan Anda memiliki file resources/views/documents/receipt.blade.php)
php artisan convert:document receipts/R-552.pdf --view=documents.receipt --disk=minio --data='{"amount":"Rp 150.000"}'
  • Menentukan layout kustom untuk konversi berbasis file:
php artisan convert:document newsletter.pdf --input=content.md --disk=public --layout=layouts.newsletter
B. Penggunaan Terprogram (misalnya, di dalam Controller) Anda juga dapat menggunakan service DocumentConverter secara langsung di dalam kode Anda untuk pembuatan dokumen dinamis.
use App\Services\DocumentConversion\DocumentConverter;
use App\Models\Order;

class OrderController extends Controller
{
    public function downloadInvoice(Order $order)
    {
        $data = [
            'order_id' => $order->id,
            'customer_name' => $order->customer->name,
            'items' => $order->items,
        ];

        $filePath = "invoices/{$order->id}.pdf";

        // Gunakan service untuk mengonversi view Blade
        DocumentConverter::fromBlade('invoices.template')
            ->withData($data)
            ->saveTo('minio', $filePath);

        // Sekarang Anda dapat mengarahkan pengguna ke URL file tersebut
        return redirect()->away(Storage::disk('minio')->url($filePath));
    }
}

4. Memperluas Pipeline

A. Membuat Input Driver Baru
  1. Buat kelas baru di app/Services/DocumentConversion/Drivers/Input yang mengimplementasikan InputDriverInterface.
  2. Implementasikan metode process(). Metode ini harus menerima konten mentah dan mengembalikan string yang kompatibel dengan Blade yang me-extend sebuah layout.
  3. Daftarkan driver baru Anda di config/documents.php dengan ekstensi file yang ditanganinya.
B. Membuat Output Driver Baru
  1. Buat kelas baru di app/Services/DocumentConversion/Drivers/Output yang mengimplementasikan OutputDriverInterface.
  2. Implementasikan metode render(). Metode ini harus menerima HTML final dan mengembalikan konten biner mentah dari file yang telah dikonversi dalam bentuk string.
  3. Daftarkan driver baru Anda di config/documents.php dengan ekstensi file outputnya.

5. Pengujian (Testing)

Sangat penting untuk menguji logika pembuatan dokumen Anda. Gunakan Storage::fake() dari Laravel untuk mencegah penulisan file ke disk selama pengujian. Berikut adalah contoh menggunakan Pest/PHPUnit:
use Illuminate\Support\Facades\Storage;
use App\Services\DocumentConversion\DocumentConverter;

it('dapat mengonversi file markdown ke pdf', function () {
    // 1. Setup: Buat disk penyimpanan palsu (fake)
    Storage::fake('minio');

    // 2. Arrange: Buat file input palsu
    $markdownContent = '# Halo {{ name }}';
    Storage::fake('local')->put('test.md', $markdownContent);
    $inputPath = Storage::disk('local')->path('test.md');

    $data = ['name' => 'Dunia'];
    $outputPath = 'output/test.pdf';

    // 3. Act: Jalankan proses konversi
    DocumentConverter::from($inputPath)
        ->withData($data)
        ->saveTo('minio', $outputPath);

    // 4. Assert: Periksa apakah file telah dibuat di disk palsu
    Storage::disk('minio')->assertExists($outputPath);
});

Lampiran 1: Pemrosesan Spreadsheet Tingkat Lanjut

A.1 Menggunakan Spreadsheet sebagai Input

Pipeline ini dapat membaca data dari file .csv dan .xlsx dan me-render-nya sebagai <table> HTML di dalam dokumen target (seperti PDF atau DOCX). Fitur ini ideal untuk membuat laporan dari data spreadsheet.

Konsep

Ketika file spreadsheet digunakan sebagai input, Input Driver yang sesuai akan melakukan langkah-langkah berikut:
  1. Mem-parsing file .csv atau .xlsx menggunakan library spreadsheet khusus.
  2. Membaca semua baris dan sel dari sheet pertama.
  3. Mengubah data ini menjadi string <table> HTML.
  4. Membungkus string tabel HTML ini di dalam direktif layout master Blade (@extends, @section).
  5. Meneruskan string Blade ini ke renderer, yang kemudian mengalir melalui sisa pipeline ke format output yang dipilih.

Engine yang Tersedia

Sistem ini mendukung beberapa engine spreadsheet, yang dapat dikonfigurasi di config/documents.php. Anda dapat memilih yang paling sesuai dengan kebutuhan Anda.
  1. MaatwebsiteInputDriver: (Default) Driver yang ramah pengguna dan kaya fitur, menggunakan paket populer maatwebsite/excel. Sangat baik untuk penggunaan umum.
  2. OpenSpoutInputDriver: Driver berkinerja tinggi dengan penggunaan memori rendah, menggunakan paket openspout/openspout. Direkomendasikan untuk file yang sangat besar.
  3. PhpSpreadsheetInputDriver: Driver yang kuat menggunakan library dasar phpoffice/phpspreadsheet. Menawarkan kontrol dan akses fitur yang maksimal.

Konfigurasi

Untuk mengganti engine, cukup edit config/documents.php dan arahkan key csv dan xlsx ke kelas driver yang Anda inginkan.
// config/documents.php
'input_drivers' => [
    // ...
    // --- Untuk menggunakan OpenSpout sebagai ganti Maatwebsite (default) ---
    'csv'  => \App\Services\DocumentConversion\Drivers\Input\OpenSpoutInputDriver::class,
    'xlsx' => \App\Services\DocumentConversion\Drivers\Input\OpenSpoutInputDriver::class,
],

Penggunaan

Perintah yang digunakan tetap sama, terlepas dari engine yang dipilih.
# Mengonversi file CSV menjadi laporan PDF
php artisan convert:document reports/sales-summary.pdf --input=data/sales.csv --disk=public

# Mengonversi file XLSX menjadi dokumen DOCX
php artisan convert:document reports/inventory.docx --input=data/inventory.xlsx --disk=public

A.2 Menghasilkan Spreadsheet sebagai Output

Pipeline ini juga dapat mengonversi dokumen sumber (seperti Markdown atau HTML) menjadi file .xlsx. Ini berguna untuk mengekspor konten terstruktur dan tidak terstruktur ke dalam format spreadsheet.

Konsep

Ini adalah konversi yang lebih canggih. Ketika .xlsx menjadi format target, Output Driver melakukan proses yang unik:
  1. Menerima HTML final yang sudah di-render sepenuhnya dari engine Blade.
  2. Mem-parsing struktur DOM HTML tersebut.
  3. Ketika menemukan elemen <table>, ia menerjemahkan baris (<tr>) dan sel (<th>, <td>) tabel secara langsung menjadi baris dan sel spreadsheet.
  4. Ketika menemukan elemen tingkat blok lainnya (<h1>, <p>, <ul>, dll.), ia mengekstrak konten teks elemen tersebut dan menempatkannya ke dalam baris spreadsheet baru di kolom pertama.
  5. Proses ini menjaga data terstruktur sekaligus konteks tekstual dari dokumen asli.

Engine yang Tersedia

Seperti halnya input, Anda memiliki pilihan engine untuk menghasilkan file XLSX.
  1. MaatwebsiteOutputDriver: (Default) Menggunakan maatwebsite/excel untuk membuat spreadsheet dengan mudah dari array PHP. Sangat nyaman dan andal.
  2. OpenSpoutOutputDriver: Menggunakan streaming writer dari openspout/openspout. Sangat baik untuk menghasilkan file XLSX yang sangat besar tanpa mencapai batas memori.
  3. PhpSpreadsheetOutputDriver: Menggunakan phpoffice/phpspreadsheet untuk membangun dokumen di dalam memori. Menawarkan kontrol mendalam atas styling sel, formula, dan fitur canggih lainnya.

Konfigurasi

Untuk mengganti engine, edit key xlsx di bagian output_drivers pada file config/documents.php.
// config/documents.php
'output_drivers' => [
    // ...
    // --- Untuk menggunakan PhpSpreadsheet sebagai ganti Maatwebsite (default) ---
    'xlsx' => \App\Services\DocumentConversion\Drivers\Output\PhpSpreadsheetOutputDriver::class,
],
Penggunaan
# Mengonversi file Markdown (berisi teks dan tabel) menjadi file XLSX
php artisan convert:document exports/invoice-data.xlsx --input=storage/app/templates/invoice.md --disk=minio
File XLSX yang dihasilkan akan berisi teks dari file Markdown di Kolom A, dengan data dari tabel terstruktur dengan benar di beberapa kolom.

Lampiran 2: Generate XLSX dengan XLSX Template

A.2.1 Konsep

Meskipun driver output standar sangat baik untuk mengonversi konten dokumen menjadi baris spreadsheet, sistem templating ini memberikan tingkat kontrol yang lebih tinggi atas tata letak dan presentasi dokumen akhir. Ide intinya adalah menggunakan file .xlsx yang sudah dirancang sebelumnya sebagai templat. Templat ini dapat berisi header, footer, logo, teks statis, dan sel yang sudah di-styling. Pipeline kemudian akan menyuntikkan data dan konten dinamis ke dalam templat ini. Proses ini ditangani oleh driver baru yang terspesialisasi: TemplatedXlsxOutputDriver. Driver ini didukung oleh library phpoffice/phpspreadsheet, karena hanya library inilah yang mampu membaca file spreadsheet yang ada sekaligus memodifikasinya.

A.2.2 Membuat Templat XLSX

Untuk menggunakan fitur ini, Anda harus terlebih dahulu membuat file templat .xlsx (misalnya, storage/app/templates/report-template.xlsx). File ini menggunakan dua jenis penanda khusus:
  1. Placeholder Global: Untuk titik data tunggal seperti judul atau tanggal, Anda dapat menempatkan placeholder bergaya Blade langsung ke dalam sel mana pun. Driver akan menemukan dan menggantinya.
  • Sintaks: {{ $nama_variabel }} atau {{ $user.name }}
  • Contoh: Sebuah sel berisi Laporan untuk: {{ $customer_name }}
  1. Penanda Awal Konten (Content Start Marker): Anda harus menetapkan satu sel di mana konten HTML dinamis utama akan mulai dimasukkan. Semua konten akan mengalir ke bawah dari titik ini.
  • Penanda: {{CONTENT_START}}
Contoh Templat (report-template.xlsx):
ABCD
1{{ $report_title }}Logo Perusahaan
2Dibuat pada:{{ $generated_on }}
3
4Detail Transaksi
5{{CONTENT_START}}

A.2.3 Pemetaan Styling HTML ke Sel

Ketika TemplatedXlsxOutputDriver memproses konten HTML, ia menerapkan styling sel dasar berdasarkan tag HTML yang ditemuinya. Ini menambahkan hierarki tipografi ke laporan Anda.
  • <h1>, <h2>, <h3>: Teks dibuat tebal dengan ukuran font yang semakin kecil.
  • <b>, <strong>: Teks dibuat tebal.
  • <i>, <em>: Teks dibuat miring.
  • <table>: Driver mengenali tabel HTML dan memetakan <tr>, <th>, dan <td> dengan benar ke baris dan sel spreadsheet, menjaga struktur tabel.

A.2.4 Konfigurasi

Untuk mengaktifkan fitur ini, pastikan TemplatedXlsxOutputDriver diatur sebagai handler untuk ekstensi .xlsx di file config/documents.php Anda.
// config/documents.php
'output_drivers' => [
    // ...
    // Driver ini sekarang menjadi default untuk membuat laporan templated yang kaya format.
    'xlsx' => \App\Services\DocumentConversion\Drivers\Output\TemplatedXlsxOutputDriver::class,

    // Anda dapat menyimpan driver lama untuk ekspor sederhana tanpa templat di bawah key yang berbeda
    'xlsx_simple' => \App\Services\DocumentConversion\Drivers\Output\MaatwebsiteOutputDriver::class,
],

A.2.5 Penggunaan

Anda mengaktifkan fitur templating dengan menentukan path ke file templat XLSX Anda. A. Menggunakan Perintah Artisan Gunakan opsi baru --output-template.
php artisan convert:document reports/MonthlyReport.xlsx \
--input=storage/app/templates/invoice.md \
--disk=public \
--output-template=storage/app/templates/report-template.xlsx \
--data='{"report_title":"Penjualan Bulanan","generated_on":"2023-11-15","customer_name":"PT Maju Jaya"}'
B. Penggunaan Terprogram Gunakan metode fluent baru ->usingOutputTemplate() pada service DocumentConverter.
use App\Services\DocumentConversion\DocumentConverter;

// ... di dalam controller atau service
$data = [
    'report_title' => 'Penjualan Bulanan',
    'generated_on' => now()->toDateString(),
    'customer_name' => 'PT Maju Jaya',
];

DocumentConverter::fromBlade('reports.monthly_sales_content')
    ->withData($data)
    ->usingOutputTemplate(storage_path('app/templates/report-template.xlsx'))
    ->saveTo('minio', 'reports/MonthlyReport.xlsx');
Sistem sekarang akan menghasilkan file XLSX yang diformat sepenuhnya berdasarkan templat Anda, diisi dengan data dinamis dan konten yang telah di-styling.