zaynasheff/document-generator

Generate DOCX documents and PDF packages from Microsoft Word templates.

Maintainers

Package info

github.com/zaynasheff/document-generator

pkg:composer/zaynasheff/document-generator

Transparency log

Statistics

Installs: 13

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.5.1 2026-07-08 06:56 UTC

This package is auto-updated.

Last update: 2026-07-08 06:57:43 UTC


README

Latest Version on Packagist Tests PHP Version License

Generate DOCX, PDF, and merged PDF packages from Microsoft Word templates using PHPWord and LibreOffice.

Document Generator is a Laravel package that provides a fluent API for generating documents from DOCX templates, converting them to PDF, generating multiple documents in a single operation, and merging them into one PDF package.

Contents

  • Features
  • Installation
  • Configuration
  • Basic Usage
  • Package Generation
  • API Reference
  • Testing
  • Contributing
  • License

Features

  • Generate DOCX documents from Microsoft Word templates
  • Replace template placeholders
  • Generate PDF documents using LibreOffice
  • Generate multiple documents in a single operation
  • Merge generated PDF documents into a single package
  • Custom output filenames
  • Fluent and expressive API
  • Laravel auto-discovery
  • Configurable LibreOffice executable
  • PHPUnit tested
  • PHPStan (max level)
  • Laravel Pint
  • GitHub Actions ready

Requirements

  • PHP 7.4 or higher
  • Laravel 8+
  • LibreOffice (required only for PDF generation)

Installation

Install the package using Composer.

composer require zaynasheff/document-generator

Publish the configuration file.

php artisan vendor:publish --tag=document-generator-config

Configuration

Set the LibreOffice executable in your .env.

Default:

DOCUMENT_GENERATOR_OFFICE_BINARY=soffice
DOCUMENT_GENERATOR_OFFICE_PROFILE=
DOCUMENT_GENERATOR_TIMEOUT=60

macOS

DOCUMENT_GENERATOR_OFFICE_BINARY=/Applications/LibreOffice.app/Contents/MacOS/soffice

Linux

DOCUMENT_GENERATOR_OFFICE_BINARY=/usr/bin/soffice

Windows

DOCUMENT_GENERATOR_OFFICE_BINARY="C:\Program Files\LibreOffice\program\soffice.exe"

If LibreOffice is available in your system PATH, simply use:

DOCUMENT_GENERATOR_OFFICE_BINARY=soffice

DOCUMENT_GENERATOR_OFFICE_PROFILE is optional. It can be used in Docker, PHP-FPM or other headless environments where LibreOffice cannot initialize its default user profile.

Example:

DOCUMENT_GENERATOR_OFFICE_PROFILE="/tmp/document-generator-profile"

Configuration File

return [

  
    'libreoffice' => [

        'binary' => env(
            'DOCUMENT_GENERATOR_OFFICE_BINARY',
            'soffice'
        ),

        'timeout' => env(
            'DOCUMENT_GENERATOR_TIMEOUT',
            60
        ),
        'profile' => env(
            'DOCUMENT_GENERATOR_OFFICE_PROFILE',
        ),

    ]

];

Basic Usage

Generate both DOCX and PDF.

use Zaynasheff\DocumentGenerator\DocumentGenerator;

$result = DocumentGenerator::make()
    ->template(
        storage_path('templates/contract.docx')
    )
    ->values([
        'FIRST_NAME' => 'John',
        'LAST_NAME'  => 'Anderson',
        'CITY'       => 'Berlin',
    ])
    ->docx()
    ->pdf()
    ->output(
        storage_path('documents')
    )
    ->generate();

Generate DOCX Only

Generate a Microsoft Word document without creating a PDF.

$result = DocumentGenerator::make()
    ->template($template)
    ->values($values)
    ->docx()
    ->output($output)
    ->generate();

Generate PDF Only

Generate only a PDF document.

$result = DocumentGenerator::make()
    ->template($template)
    ->values($values)
    ->pdf()
    ->output($output)
    ->generate();

Generate DOCX and PDF

Generate both formats in a single operation.

$result = DocumentGenerator::make()
    ->template($template)
    ->values($values)
    ->docx()
    ->pdf()
    ->output($output)
    ->generate();

Custom Output Filename

By default the generated filename is based on the template filename.

Use name() to specify your own filename.

$result = DocumentGenerator::make()
    ->template($template)
    ->values($values)
    ->name('contract_001')
    ->pdf()
    ->output($output)
    ->generate();

Generated files:

contract_001.docx
contract_001.pdf

Generation Result

The generate() method returns a GenerationResult.

$result->hasDocx();

$result->docxPath();

$result->hasPdf();

$result->pdfPath();

Example:

if ($result->hasPdf()) {

    return response()->download(
        $result->pdfPath()
    );

}

Multiple Placeholder Values

Template placeholders are passed as an associative array.

$result = DocumentGenerator::make()
    ->template($template)
    ->values([
        'FIRST_NAME' => 'John',
        'LAST_NAME'  => 'Anderson',
        'CITY'       => 'Berlin',
        'EMAIL'      => 'john@example.com',
        'PHONE'      => '+1 555 123 45 67',
    ])
    ->pdf()
    ->output($output)
    ->generate();

Supported Placeholder Types

The following value types are supported:

  • string
  • integer
  • float
  • boolean
  • null

Example:

->values([
    'NAME'      => 'John',
    'AGE'       => 35,
    'BALANCE'   => 1500.75,
    'ACTIVE'    => true,
    'COMMENT'   => null,
])

Package Generation

Generate multiple documents in a single operation.

use Zaynasheff\DocumentGenerator\DocumentPackage;

$package = DocumentPackage::make();

$package->output(
    storage_path('documents')
);

$package
    ->addDocument()
    ->template(
        storage_path('templates/contract.docx')
    )
    ->values([
        'FIRST_NAME' => 'John',
        'LAST_NAME'  => 'Anderson',
    ])
    ->name('contract')
    ->pdf();

$package
    ->addDocument()
    ->template(
        storage_path('templates/invoice.docx')
    )
    ->values([
        'FIRST_NAME' => 'John',
    ])
    ->name('invoice')
    ->pdf();

$result = $package->generate();

Generated files:

documents/
    contract.docx
    contract.pdf

    invoice.docx
    invoice.pdf

Merge PDF

Automatically merge all generated PDF files into a single document.

$package = DocumentPackage::make();

$package
    ->output(
        storage_path('documents')
    )
    ->name('package')
    ->mergePdf();

$package
    ->addDocument()
    ->template($contractTemplate)
    ->values($contractValues)
    ->name('contract')
    ->pdf();

$package
    ->addDocument()
    ->template($invoiceTemplate)
    ->values($invoiceValues)
    ->name('invoice')
    ->pdf();

$result = $package->generate();

Generated files:

documents/

    contract.docx
    contract.pdf

    invoice.docx
    invoice.pdf

    package.pdf

Multiple Copies

Generate multiple copies of the same document.

$package = DocumentPackage::make();

$package
    ->output(storage_path('documents'));

$package
    ->addDocument()
    ->template($template)
    ->values($values)
    ->name('contract')
    ->copies(3)
    ->pdf();

$result = $package->generate();

Generated files:

contract.pdf
contract_2.pdf
contract_3.pdf

Copies are generated in the specified order and are automatically included in merged PDF packages.

Blank Pages

Insert blank pages between generated documents when creating a merged PDF.

use Zaynasheff\DocumentGenerator\DocumentPackage;

$package = DocumentPackage::make();

$package
    ->output(storage_path('documents'))
    ->name('contracts')
    ->mergePdf();

$package
    ->addDocument()
    ->template($template1)
    ->values($values1)
    ->pdf();

$package->addBlankPage();

$package
    ->addDocument()
    ->template($template2)
    ->values($values2)
    ->pdf();

$result = $package->generate();

Blank pages are supported only when PDF merging is enabled.

If a blank page is added without calling mergePdf(), a DocumentGeneratorException will be thrown.

Package Result

Package generation returns a PackageResult.

$result->count();

$result->results();

$result->hasMergedPdf();

$result->mergedPdfPath();

Example:

if ($result->hasMergedPdf()) {

    return response()->download(
        $result->mergedPdfPath()
    );

}

Complete Package Example

use Zaynasheff\DocumentGenerator\DocumentPackage;

$package = DocumentPackage::make();

$package
    ->output(
        storage_path('documents')
    )
    ->name('contracts')
    ->mergePdf();

$package
    ->addDocument()
    ->template(
        storage_path('templates/contract.docx')
    )
    ->values([
        'FIRST_NAME' => 'John',
        'LAST_NAME'  => 'Anderson',
        'CITY'       => 'Berlin',
    ])
    ->name('contract')
    ->pdf();

$package
    ->addDocument()
    ->template(
        storage_path('templates/invoice.docx')
    )
    ->values([
        'FIRST_NAME' => 'John',
        'AMOUNT'     => '1500 €',
    ])
    ->name('invoice')
    ->pdf();

$result = $package->generate();

if ($result->hasMergedPdf()) {

    return response()->download(
        $result->mergedPdfPath()
    );

}

Current Capabilities

✅ DOCX generation

✅ PDF generation

✅ Custom output filenames

✅ Multiple document generation

✅ PDF package generation

✅ Merged PDF packages

✅ Fluent API

✅ Laravel auto-discovery

Why Document Generator?

Document Generator focuses on simplicity and readability.

$result = DocumentPackage::make()
    ->output($output)
    ->name('contracts')
    ->mergePdf();

$result
    ->addDocument()
    ->template($contract)
    ->values($contractData)
    ->pdf();

$result
    ->addDocument()
    ->template($invoice)
    ->values($invoiceData)
    ->pdf();

$result = $result->generate();

The package hides all low-level details of DOCX generation, PDF conversion and PDF merging behind a clean, fluent API.

API Reference

DocumentGenerator

template(string $template)

Sets the DOCX template file.

->template($template)

values(array $values)

Sets template placeholder values.

->values([
    'FIRST_NAME' => 'John',
    'LAST_NAME'  => 'Smith',
])

name(string $name)

Sets the output filename without extension.

->name('contract')

docx()

Enables DOCX generation.

->docx()

pdf()

Enables PDF generation.

->pdf()

output(string $directory)

Sets the output directory.

->output(storage_path('documents'))

generate()

Generates the requested document(s).

$result = DocumentGenerator::make()
    ->template($template)
    ->values($values)
    ->pdf()
    ->output($output)
    ->generate();

DocumentPackage

addDocument()

Adds a document to the package.

$package->addDocument();

output(string $directory)

Sets the package output directory.

$package->output(
    storage_path('documents')
);

name(string $name)

Sets the merged PDF filename.

$package->name('contracts');

Produces:

contracts.pdf

mergePdf()

Enables automatic PDF merging.

$package->mergePdf();

generate()

Generates the complete package.

$result = $package->generate();

GenerationResult

$result->hasDocx();

$result->docxPath();

$result->hasPdf();

$result->pdfPath();

PackageResult

$result->count();

$result->results();

$result->hasMergedPdf();

$result->mergedPdfPath();

Error Handling

All package exceptions extend:

Zaynasheff\DocumentGenerator\Exceptions\DocumentGeneratorException

Example:

use Zaynasheff\DocumentGenerator\Exceptions\DocumentGeneratorException;

try {

    $result = DocumentGenerator::make()
        ->template($template)
        ->pdf()
        ->output($output)
        ->generate();

} catch (DocumentGeneratorException $exception) {

    report($exception);

}

Testing

Run PHPUnit.

composer test

Run PHPStan.

composer analyse

Run Laravel Pint.

composer format:test

Run the complete quality pipeline.

composer quality

Automatically fix coding style.

composer fix

Contributing

Contributions are welcome.

Before opening a Pull Request, please make sure all quality checks pass.

composer quality

Please follow the existing coding style and architecture.

Roadmap

The following features are planned for future releases.

  • Blank pages inside document packages
  • Multiple document copies
  • ZIP package generation
  • Watermarks
  • Page numbering
  • Digital signatures

License

The MIT License (MIT).

Made with ❤️ for the Laravel community.