| Recommend this page to a friend! |
| Info | Example | Reputation | Support forum | Blog | Links |
| Last Updated | Ratings | Unique User Downloads | Download Rankings | |||||
| 2026-06-15 (Yesterday) | Not yet rated by the users | Total: Not yet counted | Not yet ranked | |||||
| Version | License | PHP version | Categories | |||
| documentgeneratorx 1.0 | BSD License | 7 | HTML, PHP 7, Documents |
| Description | Author | ||||||||||||||||||||||
This package can generate PDF documents from HTML or DOCX templates. |
| ||||||||||||||||||||||
Please read this document to learn how to install and use this PHP package to generate PDF documents from HTML or DOCX templates.
<?php |
A Laravel package to generate PDF documents from DOCX or HTML templates with variable replacement, styling support, batch generation, and queue integration for parallel processing.
composer require ayoratoumvone/documentgeneratorx
Publish the config file:
php artisan vendor:publish --tag="documentgenerator-config"
use Ayoratoumvone\Documentgeneratorx\Facades\DocumentGenerator;
// Generate PDF from DOCX template
$pdfPath = DocumentGenerator::template('template.docx')
->variables([
'name' => 'John Doe',
'photo' => 'https://example.com/photo.jpg',
])
->generate();
Use double curly braces with type annotations in your template:
{{variable_name:type,option1:value1,option2:value2}}
| Type | Syntax | Example Value |
|------|--------|---------------|
| Text | {{name:text}} | 'John Doe' |
| Number | {{age:number}} | 25 |
| Image | {{photo:image,width:200,height:100}} | 'path/to/image.jpg' |
| Date | {{date:date}} | '2024-01-15' |
| Boolean | {{active:boolean}} | true |
| Array | {{items:array}} | ['Hammer', 'Saw', 'Nail'] |
> Array placeholders fill a table column from a list and grow the table automatically. See Arrays & Repeating Table Rows.
{{logo:image}} // Default size
{{photo:image,width:200}} // Fixed width
{{banner:image,width:200,height:100}} // Fixed dimensions
{{avatar:image,ratio:1:1}} // Aspect ratio
Apply styling directly in template placeholders:
{{title:text,color:red,bold:true}}
{{name:text,font-size:18,underline:true}}
{{warning:text,color:#FF0000,background-color:#FFFF00}}
| Property | Example | Description |
|----------|---------|-------------|
| color | color:red or color:#FF0000 | Text color |
| bold | bold:true | Bold text |
| italic | italic:true | Italic text |
| underline | underline:true | Underlined text |
| font-size | font-size:14 | Font size in points |
| font-family | font-family:Arial | Font family |
| background-color | background-color:#FFFF00 | Highlight color |
red, green, blue, black, white, yellow, orange, purple, pink, gray, brown, navy, teal, maroon
> _Available since v2.0.7._
Use the array type to render a list of values down a column. The value you
pass is a plain array of strings (numbers, booleans and dates work too ? they are
stringified). One value is placed per row, and the table grows by itself to
fit the data.
{{items:array}}
['items' => ['Hammer', 'Saw', 'Nail']]
Put the placeholder in one row of a table. That row becomes the template:
Place an array placeholder in each column of the same row. The row is cloned to the length of the longest list; shorter columns simply leave blank cells.
DOCX template (a 4-column table):
| Numero | Nom | Q | Dimission |
|--------|-----|---|-----------|
| {{nums:array}} | {{noms:array}} | {{qs:array}} | {{dims:array}} |
PHP code:
DocumentGenerator::template('inventory.docx')
->variables([
'nums' => ['1', '2', '3'],
'noms' => ['Hammer', 'Saw', 'Nail'],
'qs' => ['10', '5', '200'],
'dims' => ['20cm', '40cm', '3cm'],
])
->generate('inventory.pdf');
Result ? the single placeholder row becomes three filled rows:
| Numero | Nom | Q | Dimission | |--------|-----|---|-----------| | 1 | Hammer | 10 | 20cm | | 2 | Saw | 5 | 40cm | | 3 | Nail | 200 | 3cm |
Array placeholders accept the same style options as text:
{{noms:array,bold:true,color:#2c3e50}}
If an array placeholder is not inside a table, the values are stacked on
separate lines within the same paragraph (joined with line breaks).
Methods for generating one document at a time.
| Method | Description | Returns |
|--------|-------------|---------|
| generate($path) | Generate PDF to file path | File path |
| download($filename) | Generate and return download response | HTTP Response |
| generateToStorage($path, $disk) | Generate and save to Laravel storage | Storage path |
use Ayoratoumvone\Documentgeneratorx\Facades\DocumentGenerator;
$pdfPath = DocumentGenerator::template('invoice.docx')
->variables([
'customer_name' => 'John Doe',
'total' => '$1,234.00',
])
->generate('invoices/invoice-001.pdf');
// Returns a download response - works for SINGLE document only
return DocumentGenerator::template('contract.docx')
->variables(['name' => 'John Doe'])
->download('contract.pdf');
$path = DocumentGenerator::template('report.docx')
->variables(['title' => 'Monthly Report'])
->generateToStorage('reports/march-2024.pdf', 'public');
Generate multiple documents at once. Returns an array of results.
> Note: download() is NOT available for batch generation. You cannot download multiple files in a single HTTP response. For batch downloads, generate files then create a ZIP archive.
| Method | Description | Returns |
|--------|-------------|---------|
| generateBatch($documents) | Generate multiple PDFs (same template) | Array of results |
| batchGenerate($documents) | Generate multiple PDFs (different templates) | Array of results |
use Ayoratoumvone\Documentgeneratorx\Facades\DocumentGenerator;
$generator = DocumentGenerator::template('certificate.docx');
$results = $generator->generateBatch([
['variables' => ['name' => 'Alice Johnson'], 'output' => 'certs/alice.pdf'],
['variables' => ['name' => 'Bob Smith'], 'output' => 'certs/bob.pdf'],
['variables' => ['name' => 'Carol White'], 'output' => 'certs/carol.pdf'],
]);
// Check results
foreach ($results as $result) {
if ($result['success']) {
echo "Generated: {$result['path']}\n";
} else {
echo "Failed: {$result['error']}\n";
}
}
use Ayoratoumvone\Documentgeneratorx\DocumentGenerator;
$results = DocumentGenerator::batchGenerate([
[
'template' => 'invoice.docx',
'variables' => ['customer' => 'John', 'total' => '$500'],
'output' => 'docs/invoice.pdf',
],
[
'template' => 'contract.docx',
'variables' => ['client' => 'Jane', 'date' => '2024-01-15'],
'output' => 'docs/contract.pdf',
],
]);
$results = $generator->generateBatch($documents, false, function($completed, $total, $path) {
$percent = round(($completed / $total) * 100);
echo "Progress: {$percent}% ({$completed}/{$total})\n";
});
To let users download multiple documents, create a ZIP file:
use ZipArchive;
// Generate batch
$results = $generator->generateBatch($documents);
// Create ZIP with successful files
$zipPath = storage_path('app/temp/documents.zip');
$zip = new ZipArchive();
$zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);
foreach ($results as $result) {
if ($result['success']) {
$zip->addFile($result['path'], basename($result['path']));
}
}
$zip->close();
// Return ZIP download
return response()->download($zipPath, 'documents.zip')->deleteFileAfterSend(true);
For generating many documents simultaneously, use Laravel's queue system with the built-in job and events. Each document gets a system-generated documentId that you can use to track its progress.
use Ayoratoumvone\Documentgeneratorx\Jobs\GenerateDocument;
// Create the job to get the document ID
$job = new GenerateDocument(
templatePath: storage_path('templates/invoice.docx'),
variables: ['customer' => 'John Doe', 'total' => '$1,234'],
outputPath: storage_path('app/invoices/invoice-001.pdf')
);
// Get the document ID for tracking (store this in your database)
$documentId = $job->documentId; // e.g., "doc_550e8400-e29b-41d4-a716-446655440000"
// Save to your database
DocumentRequest::create([
'document_id' => $documentId,
'user_id' => auth()->id(),
'status' => 'pending',
]);
// Dispatch the job
dispatch($job);
// Return the document ID to user so they can check status later
return response()->json(['document_id' => $documentId, 'status' => 'processing']);
Use the GenerateDocumentBatch helper:
use Ayoratoumvone\Documentgeneratorx\Jobs\GenerateDocumentBatch;
// Create batch
$batchHelper = GenerateDocumentBatch::create([
['template' => 'invoice.docx', 'variables' => ['name' => 'Alice'], 'output' => 'alice.pdf'],
['template' => 'invoice.docx', 'variables' => ['name' => 'Bob'], 'output' => 'bob.pdf'],
['template' => 'invoice.docx', 'variables' => ['name' => 'Carol'], 'output' => 'carol.pdf'],
]);
// Get all document IDs BEFORE dispatching (store these in your database)
$documentIds = $batchHelper->getDocumentIds();
// ['doc_abc123...', 'doc_def456...', 'doc_ghi789...']
// Save to your database for tracking
foreach ($documentIds as $documentId) {
DocumentRequest::create([
'document_id' => $documentId,
'user_id' => auth()->id(),
'status' => 'pending',
]);
}
// Now dispatch
$batch = $batchHelper
->name('Monthly Invoices')
->onQueue('documents')
->dispatch();
// Return document IDs to user
return response()->json([
'batch_id' => $batchHelper->getBatchId(),
'document_ids' => $documentIds,
'status' => 'processing',
]);
When documents complete (or fail), events fire with the documentId. Use listeners to update your database:
// In your EventServiceProvider
protected $listen = [
\Ayoratoumvone\Documentgeneratorx\Events\DocumentGenerated::class => [
\App\Listeners\UpdateDocumentStatus::class,
],
\Ayoratoumvone\Documentgeneratorx\Events\DocumentGenerationFailed::class => [
\App\Listeners\HandleDocumentFailure::class,
],
];
// app/Listeners/UpdateDocumentStatus.php
class UpdateDocumentStatus
{
public function handle(DocumentGenerated $event): void
{
// Find your record using the document ID
$request = DocumentRequest::where('document_id', $event->documentId)->first();
if ($request) {
$request->update([
'status' => 'completed',
'file_path' => $event->outputPath,
'completed_at' => now(),
]);
// Notify the user
$request->user->notify(new DocumentReadyNotification($event->outputPath));
}
}
}
// Controller: Start document generation
public function generateInvoice(Request $request)
{
$job = new GenerateDocument(
'invoice.docx',
['customer' => $request->customer_name, 'total' => $request->total],
"invoices/{$request->invoice_id}.pdf"
);
// Store for tracking
DocumentRequest::create([
'document_id' => $job->documentId,
'user_id' => auth()->id(),
'type' => 'invoice',
'status' => 'processing',
]);
dispatch($job);
return response()->json([
'document_id' => $job->documentId,
'message' => 'Document is being generated',
]);
}
// Controller: Check status
public function checkStatus(string $documentId)
{
$request = DocumentRequest::where('document_id', $documentId)
->where('user_id', auth()->id())
->firstOrFail();
return response()->json([
'document_id' => $documentId,
'status' => $request->status,
'file_path' => $request->file_path,
'completed_at' => $request->completed_at,
]);
}
The package fires events at each stage of document generation. Use these to add custom logic.
| Event | When Fired | Use Case |
|-------|------------|----------|
| DocumentGenerating | Before generation starts | Validate, log start |
| DocumentGenerated | After successful generation | Notify user, move file |
| DocumentGenerationFailed | When generation fails | Log error, notify admin |
| BatchGenerationCompleted | When batch finishes | Zip files, send summary |
1. Publish example listeners:
php artisan vendor:publish --tag="documentgenerator-listeners"
2. Register listeners in EventServiceProvider:
// app/Providers/EventServiceProvider.php
use Ayoratoumvone\Documentgeneratorx\Events\DocumentGenerated;
use Ayoratoumvone\Documentgeneratorx\Events\DocumentGenerationFailed;
use Ayoratoumvone\Documentgeneratorx\Events\BatchGenerationCompleted;
use App\Listeners\DocumentGenerator\LogDocumentGenerated;
use App\Listeners\DocumentGenerator\NotifyDocumentReady;
use App\Listeners\DocumentGenerator\HandleGenerationFailed;
use App\Listeners\DocumentGenerator\HandleBatchCompleted;
protected $listen = [
DocumentGenerated::class => [
LogDocumentGenerated::class,
NotifyDocumentReady::class,
],
DocumentGenerationFailed::class => [
HandleGenerationFailed::class,
],
BatchGenerationCompleted::class => [
HandleBatchCompleted::class,
],
];
// app/Listeners/DocumentGenerator/NotifyDocumentReady.php
namespace App\Listeners\DocumentGenerator;
use Ayoratoumvone\Documentgeneratorx\Events\DocumentGenerated;
use App\Models\DocumentRequest;
use App\Notifications\DocumentReadyNotification;
class NotifyDocumentReady
{
public function handle(DocumentGenerated $event): void
{
// Find the document request using the system-generated documentId
$request = DocumentRequest::where('document_id', $event->documentId)->first();
if ($request) {
// Update status
$request->update([
'status' => 'completed',
'file_path' => $event->outputPath,
]);
// Notify the user who requested this document
$request->user->notify(new DocumentReadyNotification(
$event->outputPath,
$event->getFileSizeFormatted()
));
}
}
}
// app/Listeners/DocumentGenerator/HandleBatchCompleted.php
use Ayoratoumvone\Documentgeneratorx\Events\BatchGenerationCompleted;
use ZipArchive;
class HandleBatchCompleted
{
public function handle(BatchGenerationCompleted $event): void
{
if (!$event->isFullySuccessful()) {
Log::warning("Batch {$event->batchId} had {$event->failedCount} failures");
return;
}
// Create ZIP with all documents
$zipPath = storage_path("app/batches/{$event->batchId}.zip");
$zip = new ZipArchive();
$zip->open($zipPath, ZipArchive::CREATE);
foreach ($event->getSuccessfulPaths() as $path) {
$zip->addFile($path, basename($path));
}
$zip->close();
Log::info("Batch ZIP created: {$zipPath}");
}
}
Start queue workers to process document generation jobs:
# Single worker
php artisan queue:work
# Multiple workers for parallel processing
php artisan queue:work --queue=documents &
php artisan queue:work --queue=documents &
php artisan queue:work --queue=documents &
# Using Supervisor (production)
# See Laravel docs: https://laravel.com/docs/queues#supervisor-configuration
Uses LibreOffice for pixel-perfect PDF conversion. Recommended for production.
Install LibreOffice:
- Windows: Download
- Linux: sudo apt install libreoffice
- macOS: brew install libreoffice
DOCUMENT_PDF_CONVERSION=libreoffice
LIBREOFFICE_PATH="C:\Program Files\LibreOffice\program\soffice.exe"
No external dependencies, but may not preserve all formatting.
DOCUMENT_PDF_CONVERSION=dompdf
If LibreOffice is not installed, you'll get a helpful error:
LibreOffice is not installed or not found on this system.
To fix this, you have two options:
1. Install LibreOffice (recommended for best PDF quality):
Download from: https://www.libreoffice.org/download/download/
Then set the path in your .env file:
LIBREOFFICE_PATH="C:\Program Files\LibreOffice\program\soffice.exe"
2. Use HTML-based conversion (no LibreOffice required):
Set in your .env file:
DOCUMENT_PDF_CONVERSION=dompdf
// config/documentgenerator.php
return [
// PDF conversion method: 'libreoffice' (default) or 'dompdf'
'pdf_conversion' => env('DOCUMENT_PDF_CONVERSION', 'libreoffice'),
// LibreOffice executable path (auto-detected if not set)
'libreoffice_path' => env('LIBREOFFICE_PATH', null),
// Default template storage path
'template_path' => storage_path('app/document-templates'),
// Default output path for permanent files
'output_path' => storage_path('app/generated-documents'),
// Save to temp directory (auto-deleted)
'temp_output' => true,
// Delete file after download() response
'delete_after_download' => true,
// Cleanup temp files on script end
'cleanup_on_shutdown' => true,
// Default storage disk
'disk' => 'local',
];
require 'vendor/autoload.php';
use Ayoratoumvone\Documentgeneratorx\Generators\DocxToPdfGenerator;
$generator = new DocxToPdfGenerator();
// Set LibreOffice path
$generator->setLibreOfficePath('C:\Program Files\LibreOffice\program\soffice.exe');
// Generate PDF
$generator->generate(
'template.docx',
['name' => 'John Doe', 'date' => '2024-01-15'],
'output.pdf'
);
MIT License. See LICENSE.md for details.
| File | Role | Description | ||
|---|---|---|---|---|
| Data | Auxiliary data | |||
| Data | Auxiliary data | |||
| Data | Auxiliary data | |||
| Data | Auxiliary data | |||
| Data | Auxiliary data | |||
| Doc. | Documentation | |||
| / | examples |
| File | Role | Description |
|---|---|---|
| |
Example | Example script |
| |
Example | Example script |
| / | src |
| File | Role | Description | ||
|---|---|---|---|---|
| |
Class | Class source | ||
| |
Class | Class source | ||
| / | src | / | Events |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| |
Class | Class source |
| |
Class | Class source |
| / | src | / | Exceptions |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| / | src | / | Generators |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| / | src | / | Jobs |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| / | src | / | Processors |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| / | stubs | / | Listeners |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| |
Class | Class source |
| |
Class | Class source |
| / | tests |
| File | Role | Description | ||
|---|---|---|---|---|
| |
Example | Example script | ||
| |
Example | Example script | ||
| / | tests | / | Feature |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| / | tests | / | templates |
| File | Role | Description |
|---|---|---|
| |
Data | Auxiliary data |
| |
Doc. | Documentation |
| / | tests | / | Unit |
| File | Role | Description |
|---|---|---|
| |
Class | Class source |
| |
Class | Class source |
| The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page. |
| Version Control | Unique User Downloads | |||||||
| 100% |
|
| Applications that use this package |
If you know an application of this package, send a message to the author to add a link here.