plusforta/pdf-forms

Pure PHP library for filling AcroForm fields in PDF documents

Maintainers

Package info

gitlab.com/plusforta/public/pdf-forms

Issues

pkg:composer/plusforta/pdf-forms

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 0

1.0.3 2026-04-06 07:18 UTC

This package is auto-updated.

Last update: 2026-04-06 07:24:21 UTC


README

pipeline status coverage report

A pure PHP library for filling AcroForm fields in PDF documents. No external binaries required — no pdftk, no Java, no command-line tools.

Requirements

  • PHP 8.1 or higher
  • ext-zlib (included in most PHP installations)

Installation

composer require plusforta/pdf-forms

Usage

Fill form fields and save

use PlusForta\PdfForms\PdfForm;

PdfForm::open('template.pdf')
    ->fill([
        'name' => 'Max Mustermann',
        'email' => 'max@example.com',
        'date' => '2024-01-15',
    ])
    ->save('output.pdf');

Set fields individually

PdfForm::open('template.pdf')
    ->set('name', 'Max Mustermann')
    ->set('date', '2024-01-15')
    ->save('output.pdf');

Return PDF as string

Useful for HTTP responses or storing in S3:

$pdfBytes = PdfForm::open('template.pdf')
    ->fill(['name' => 'Max Mustermann'])
    ->toString();

// e.g. in Laravel
return response($pdfBytes, 200, [
    'Content-Type' => 'application/pdf',
]);

Load from bytes

$pdfBytes = Storage::get('templates/form.pdf');

PdfForm::load($pdfBytes)
    ->fill(['name' => 'Max Mustermann'])
    ->save('output.pdf');

Inspect available fields

$fields = PdfForm::open('template.pdf')->getFields();

foreach ($fields as $name => $field) {
    echo "$name ({$field->type->value})\n";
}

Each field is a PlusForta\PdfForms\Form\Field object with properties: name, type, value, options.

Flatten fields

Flattening bakes field values into the page as static content. The resulting PDF has no editable form fields.

// Flatten all fields
PdfForm::open('template.pdf')
    ->fill(['name' => 'Max Mustermann'])
    ->flatten()
    ->save('output.pdf');

// Flatten specific fields only
PdfForm::open('template.pdf')
    ->fill(['name' => 'Max', 'date' => '2024-01-15'])
    ->flatten(['name'])  // only 'name' is flattened; 'date' stays editable
    ->save('output.pdf');

Appearance streams and /NeedAppearances

An appearance stream is a small drawing program embedded in the PDF that tells viewers exactly how to render a form field — its text, font, size, color, and position. Without one, a viewer has no instructions for displaying the field's value.

When a PDF sets /NeedAppearances true, it tells the viewer: "Ignore any embedded appearance streams and regenerate the visual appearance of every field yourself." This is a safety net — it guarantees fields display their values even if appearance streams are missing or outdated, but it hands control of rendering to the viewer.

This library generates its own appearance streams for text fields, so you have two choices:

/NeedAppearances true (default)/NeedAppearances false
How it worksViewer regenerates field appearances from scratchViewer uses the library's embedded appearance streams
CompatibilityWorks in all viewers, even if appearance streams are missingRequires valid appearance streams (this library generates them)
Visual consistencyRendering varies by viewer (fonts, spacing may differ)Looks the same across viewers
Side effectsAdobe Acrobat may prompt "Do you want to save?" on openNo prompts or regeneration

For most use cases, the default (true) is the safest option. If you need consistent rendering across viewers or want to avoid Acrobat's save prompt, disable it:

PdfForm::open('template.pdf')
    ->fill(['name' => 'Max Mustermann'])
    ->needAppearances(false)
    ->save('output.pdf');

Supported field types

TypeReadFillAppearance stream
Text (/Tx)YesYesYes
Checkbox (/Btn)YesYesNo (uses existing)
Radio button (/Btn)YesYesNo (uses existing)
Dropdown (/Ch)YesYesNo (uses existing)
Listbox (/Ch)YesYesNo (uses existing)
Signature (/Sig)YesNoNo

Error handling

All errors throw exceptions extending PlusForta\PdfForms\Exception\PdfFormsException:

ExceptionWhen
FileNotFoundExceptionInput file doesn't exist
InvalidPdfExceptionPDF can't be parsed or is encrypted
NoFormFieldsExceptionPDF has no AcroForm dictionary
FieldNotFoundExceptionReferencing a field name that doesn't exist
WriteExceptionCan't write to output path

Limitations

  • Encrypted PDFs are not supported.
  • XFA forms (XML-based) are not supported. Only classic AcroForm fields.
  • Cross-reference streams (PDF 1.5+ compressed xref) are not yet supported. Classic xref tables work fine.
  • Right-to-left text is not supported in appearance streams.
  • Text that overflows a field rectangle is clipped, not auto-sized.

Running tests

composer install
vendor/bin/phpunit

License

MIT