Skip to content

tudorr89/pdfcombiner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PDF Combine

Latest Version License PHP Version

A modern PHP package to combine multiple PDF files with page-level granularity. Built on TCPDF and FPDI for reliable rendering. Supports Laravel auto-discovery (10.x, 11.x, 12.x) and standalone usage.


Requirements

  • PHP ^8.2
  • Composer

Under the hood the package depends on tecnickcom/tcpdf and setasign/fpdi — both are pulled in automatically.

Installation

composer require tudorr89/pdfcombiner

Laravel

If you use Laravel ≥ 5.5 the package registers itself via auto-discovery. No manual setup required.

Publish the config (optional):

php artisan vendor:publish --tag=pdfcombine-config

Standalone (non-Laravel)

require 'vendor/autoload.php';

use PdfCombine\PDFCombiner;

$combiner = new PDFCombiner;

Quick Start

Combine two files and save to disk

$combiner = new \PdfCombine\PDFCombiner();

$combiner
    ->addFile('/path/to/report.pdf')
    ->addFile('/path/to/appendix.pdf')
    ->save('/path/to/combined.pdf');

Combine specific pages only

$combiner
    ->addFile('/path/to/large.pdf', [1, 5, 7])  // pages 1, 5, 7
    ->addFile('/path/to/summary.pdf')            // all pages
    ->save('/path/to/result.pdf');

Stream to browser for download

$combiner
    ->addFile('/path/to/doc.pdf')
    ->addRaw($pdfBinaryString, 'attachment.pdf')
    ->download('final-report.pdf');

Get PDF contents as a string

$content = $combiner
    ->addFile('/path/to/doc.pdf')
    ->blob();

// or
$content = $combiner->stream();

Laravel — Dependency Injection

use PdfCombine\Contracts\PDFCombinerInterface;

class ReportController
{
    public function combine(PDFCombinerInterface $combiner)
    {
        $combiner
            ->addFile(storage_path('reports/january.pdf'))
            ->addFile(storage_path('reports/february.pdf'))
            ->save(storage_path('reports/q1.pdf'));

        return response()->download(storage_path('reports/q1.pdf'));
    }
}

Laravel — Facade

use PDFCombine;

PDFCombine::addFile('/path/to/a.pdf')
    ->addFile('/path/to/b.pdf')
    ->download('combined.pdf');

API Reference

addFile(string $path, array $pages = []): self

Add a PDF file from disk.

  • $path — absolute or relative path to a .pdf file
  • $pages — optional array of page numbers to include (1-indexed). Empty array = all pages.
$combiner->addFile('/path/to/doc.pdf');                // all pages
$combiner->addFile('/path/to/doc.pdf', [1, 3]);        // pages 1 and 3 only
$combiner->addFile('/path/to/doc.pdf', range(5, 10));  // pages 5 through 10

addFiles(array $paths): self

Add multiple files at once. Accepts plain paths or [path, pages] tuples.

$combiner->addFiles([
    '/path/to/cover.pdf',
    ['/path/to/body.pdf', [1, 2, 3]],
    '/path/to/back.pdf',
]);

addRaw(string $content, string $filename = 'document.pdf', array $pages = []): self

Add PDF content from a raw binary string (e.g. from an HTTP response, database BLOB, or upload stream).

$rawPdf = file_get_contents('https://example.com/remote.pdf');
$combiner->addRaw($rawPdf, 'remote.pdf');

save(string $outputPath): bool

Combine all added files and write the result to $outputPath. Returns true on success.

$combiner->addFile('a.pdf')->addFile('b.pdf')->save('combined.pdf');

download(string $filename = 'combined.pdf'): void

Send the combined PDF to the browser as a download (sends Content-Disposition: attachment headers + body). Does not call exit — middleware and terminating callbacks still run.

$combiner->download('quarterly-report.pdf');

In Laravel, prefer streaming the body yourself so you stay on the full response pipeline:

return response()->streamDownload(
    fn () => print($combiner->stream()),
    'quarterly-report.pdf',
    ['Content-Type' => 'application/pdf'],
);

stream(string $filename = 'combined.pdf'): string

Return the combined PDF as a raw binary string.

$pdf = $combiner->stream();
// store in S3, send via email attachment, etc.

blob(): string

Alias for stream().

getPageCount(): int

Return the total number of pages that would be included in the output (honours page-range filters).

$combiner
    ->addFile('doc.pdf', [2, 4])
    ->addFile('summary.pdf');

echo $combiner->getPageCount(); // 2 + all pages of summary.pdf

getFileCount(): int

Return the number of files currently queued.

reset(): self

Clear all queued files. Preserves orientation / unit / paper size so the same configured instance can be reused.

$combiner->reset();

resetConfig(): self

Restore orientation / unit / paper size to their defaults (P / mm / A4). Does not touch the file queue.

$combiner->resetConfig();

Configuration

Orientation

use PdfCombine\Contracts\PDFCombinerInterface;

$combiner->withOrientation(PDFCombinerInterface::ORIENTATION_PORTRAIT);   // 'P'
$combiner->withOrientation(PDFCombinerInterface::ORIENTATION_LANDSCAPE);  // 'L'

Unit of measurement

$combiner->withUnit(PDFCombinerInterface::UNIT_MM);
$combiner->withUnit(PDFCombinerInterface::UNIT_CM);
$combiner->withUnit(PDFCombinerInterface::UNIT_IN);
$combiner->withUnit(PDFCombinerInterface::UNIT_PT);

Paper size

// Named constants
$combiner->withPaperSize(PDFCombinerInterface::SIZE_A4);
$combiner->withPaperSize(PDFCombinerInterface::SIZE_A5);
$combiner->withPaperSize(PDFCombinerInterface::SIZE_A6);
$combiner->withPaperSize(PDFCombinerInterface::SIZE_LETTER);
$combiner->withPaperSize(PDFCombinerInterface::SIZE_LEGAL);

// Or any TCPDF-compatible format string
$combiner->withPaperSize('A3');
$combiner->withPaperSize('Legal');

// Or custom [width, height] array (in the unit defined above)
$combiner->withPaperSize([210, 297]); // A4 in mm

Laravel config (config/pdfcombine.php)

return [
    'orientation' => env('PDFCOMBINE_ORIENTATION', 'P'),
    'unit'        => env('PDFCOMBINE_UNIT', 'mm'),
    'paper_size'  => env('PDFCOMBINE_PAPER_SIZE', 'A4'),
];

Environment variables override the defaults:

PDFCOMBINE_ORIENTATION=L
PDFCOMBINE_UNIT=in
PDFCOMBINE_PAPER_SIZE=Letter

Fluent interface

All setter and adder methods return $this, so you can chain calls:

$content = $combiner
    ->withOrientation(PDFCombinerInterface::ORIENTATION_LANDSCAPE)
    ->withPaperSize(PDFCombinerInterface::SIZE_A3)
    ->addFile('cover.pdf')
    ->addFile('body.pdf', range(2, 10))
    ->addFile('back.pdf')
    ->stream();

Error handling

The package throws typed exceptions from PdfCombine\Exceptions\PDFCombineException:

Method Exception message
File not found PDF file not found at path: ...
Invalid / unreadable PDF The file at '...' is not a valid PDF or could not be read.
No files added No PDF files have been added to combine.
Save failed Failed to save the combined PDF to: ...
Page out of range Requested page X is out of range. The document has Y pages.
use PdfCombine\Exceptions\PDFCombineException;

try {
    $combiner->addFile('/missing.pdf')->save('/out.pdf');
} catch (PDFCombineException $e) {
    logger()->error('PDF combine failed: ' . $e->getMessage());
}

Changelog

See the releases page on GitHub.


License

MIT — see the LICENSE file for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages