PHPackages                             stitch-digital/laravel-pdfmerger - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [PDF &amp; Document Generation](/categories/documents)
4. /
5. stitch-digital/laravel-pdfmerger

ActiveLibrary[PDF &amp; Document Generation](/categories/documents)

stitch-digital/laravel-pdfmerger
================================

Modern PDF merger for Laravel with fluent API and full type safety

2.0.3(5mo ago)01.9k↓65.9%MITPHPPHP ^8.2CI passing

Since Jan 23Pushed 3w agoCompare

[ Source](https://github.com/stitch-digital/laravel-pdfmerger)[ Packagist](https://packagist.org/packages/stitch-digital/laravel-pdfmerger)[ Docs](https://github.com/stitch-digital/laravel-pdfmerger)[ RSS](/packages/stitch-digital-laravel-pdfmerger/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (6)Dependencies (9)Versions (8)Used By (0)

Laravel PDFMerger
=================

[](#laravel-pdfmerger)

[![Latest Version on Packagist](https://camo.githubusercontent.com/b238de94ba96d26e9575ec137d493bd1aa97c341598ba848bbbaa35fd95f3b6f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7374697463682d6469676974616c2f6c61726176656c2d7064666d65726765722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stitch-digital/laravel-pdfmerger)[![GitHub Tests Action Status](https://camo.githubusercontent.com/df513a4a1f22e7d195d43e0a3a8f3a825d2740b451b19e4e6ec35cc9b6ce66d3/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7374697463682d6469676974616c2f6c61726176656c2d7064666d65726765722f74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/stitch-digital/laravel-pdfmerger/actions?query=workflow%3Atests+branch%3Amaster)[![GitHub Code Quality Action Status](https://camo.githubusercontent.com/e03e5bbdbb3ea1dc3345286b7194233fe05fe8369cef8d868d97e185f87ac8fb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7374697463682d6469676974616c2f6c61726176656c2d7064666d65726765722f636f64652d7175616c6974792e796d6c3f6272616e63683d6d6173746572266c6162656c3d636f64652532307175616c697479267374796c653d666c61742d737175617265)](https://github.com/stitch-digital/laravel-pdfmerger/actions?query=workflow%3Acode-quality+branch%3Amaster)[![Total Downloads](https://camo.githubusercontent.com/f85483762bc93c20dc1dec61a5f5d34b3eae53ed6187b981b292459089835f24/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7374697463682d6469676974616c2f6c61726176656c2d7064666d65726765722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stitch-digital/laravel-pdfmerger)

A modern, fluent PDF merger for Laravel with full type safety and an elegant API. Merge multiple PDF files with ease using a developer-friendly interface.

[![Laravel PDFMerger](laravel-pdfmerger.png)](laravel-pdfmerger.png)

Features
--------

[](#features)

- 🚀 **Modern PHP**: Built for PHP 8.2+ with strict types
- 🎯 **Fluent API**: Chainable methods following Laravel conventions
- 🔒 **Type Safe**: Full type hints and return types for better IDE support
- 🌐 **URL Support**: Add PDFs from both local paths and remote URLs
- 🎨 **Enum Support**: Use `Orientation` enum for better developer experience
- 🎨 **Laravel 10-11**: Compatible with Laravel 10 and 11
- 📦 **Auto-Discovery**: Zero configuration with Laravel package auto-discovery
- 🧪 **Fully Tested**: Comprehensive test suite with PHPUnit
- 📝 **Well Documented**: Clear examples and inline documentation

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Laravel 10.0 or 11.0

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require stitch-digital/laravel-pdfmerger
```

The package will automatically register itself via Laravel's package discovery.

### Publish Configuration (Optional)

[](#publish-configuration-optional)

You can publish the configuration file if you want to customize default settings:

```
php artisan vendor:publish --tag=pdfmerger-config
```

Usage
-----

[](#usage)

### Basic Example

[](#basic-example)

```
use StitchDigital\PDFMerger\Facades\PDFMergerFacade as PDFMerger;

PDFMerger::make()
    ->addPDF('/path/to/first.pdf')
    ->addPDF('/path/to/second.pdf')
    ->merge()
    ->save('merged_output.pdf');
```

### Fluent API with Method Chaining

[](#fluent-api-with-method-chaining)

```
PDFMerger::make()
    ->addPDF('/path/to/file1.pdf', pages: [1, 2, 3])
    ->addPDF('/path/to/file2.pdf', pages: 'all')
    ->addPDF('/path/to/file3.pdf', pages: [1])
    ->merge()
    ->save('output.pdf');
```

### Selecting Specific Pages

[](#selecting-specific-pages)

```
PDFMerger::make()
    ->addPDF($file, 'all')           // Add all pages
    ->addPDF($file, [1])             // Add page 1 only
    ->addPDF($file, [1, 3, 5])       // Add pages 1, 3, and 5
    ->merge()
    ->save();
```

### Using Named Parameters (PHP 8.0+)

[](#using-named-parameters-php-80)

```
use StitchDigital\PDFMerger\Enums\Orientation;

PDFMerger::make()
    ->addPDF(
        filePath: '/path/to/file.pdf',
        pages: [1, 3, 5],
        orientation: Orientation::Landscape
    )
    ->merge()
    ->save('output.pdf');
```

### Setting Orientation

[](#setting-orientation)

You can set orientation using strings or the `Orientation` enum for better IDE support and type safety:

```
use StitchDigital\PDFMerger\Enums\Orientation;

// Using enum (recommended)
PDFMerger::make()
    ->orientation(Orientation::Landscape)
    ->addPDF($file1)
    ->addPDF($file2)
    ->merge()
    ->save();

// Using string (still supported)
PDFMerger::make()
    ->orientation('L')  // 'L' for Landscape, 'P' for Portrait
    ->addPDF($file1)
    ->addPDF($file2)
    ->merge()
    ->save();

// Per-file orientation
PDFMerger::make()
    ->addPDF($file1, pages: 'all', orientation: Orientation::Portrait)
    ->addPDF($file2, pages: 'all', orientation: Orientation::Landscape)
    ->merge()
    ->save();
```

### Duplex Printing Support

[](#duplex-printing-support)

Add blank pages between documents to support double-sided printing:

```
PDFMerger::make()
    ->duplex(true)
    ->addPDF($file1)
    ->addPDF($file2)
    ->merge()
    ->save();

// Or use duplexMerge directly
PDFMerger::make()
    ->addPDF($file1)
    ->addPDF($file2)
    ->duplexMerge()
    ->save();
```

### Working with String Content

[](#working-with-string-content)

```
$pdfContent = file_get_contents('/path/to/file.pdf');

PDFMerger::make()
    ->addString($pdfContent, pages: [1, 2])
    ->merge()
    ->save();
```

### Using URLs (Remote PDFs)

[](#using-urls-remote-pdfs)

The package can automatically download and merge PDFs from remote URLs:

```
// Using remote URLs
PDFMerger::make()
    ->addPDF('https://example.com/document1.pdf')
    ->addPDF('https://example.com/document2.pdf')
    ->merge()
    ->save('merged.pdf');

// With Laravel's asset() helper
PDFMerger::make()
    ->addAll(asset('pdfs/document1.pdf'))
    ->addAll(asset('pdfs/document2.pdf'))
    ->merge()
    ->save('merged.pdf');

// Mix local and remote PDFs
PDFMerger::make()
    ->addPDF('/local/path/document.pdf')
    ->addPDF('https://example.com/remote-document.pdf')
    ->addPDF(public_path('pdfs/another.pdf'))
    ->merge()
    ->save();

// URLs support all the same options as local files
PDFMerger::make()
    ->addPDF('https://example.com/doc.pdf', pages: [1, 3, 5])
    ->addPDF('https://example.com/doc2.pdf', orientation: Orientation::Landscape)
    ->merge()
    ->save();
```

Downloaded PDFs are automatically stored in temporary files and cleaned up after the merge operation completes.

#### URL Security Configuration

[](#url-security-configuration)

URL downloads can be configured in `config/pdfmerger.php`:

```
return [
    // Enable or disable URL downloads
    'allow_urls' => env('PDFMERGER_ALLOW_URLS', true),

    // Timeout for URL downloads (seconds)
    'url_download_timeout' => env('PDFMERGER_DOWNLOAD_TIMEOUT', 30),

    // Verify SSL certificates for HTTPS URLs
    'url_verify_ssl' => env('PDFMERGER_VERIFY_SSL', true),
];
```

**Automatic Local Development Support:**

SSL verification is **automatically disabled** when `APP_ENV=local`, making it work seamlessly with local domains like `.test`, `.local`, or self-signed certificates. No configuration needed!

**For production environments**, SSL verification is automatically enabled when `APP_ENV=production`, ensuring secure connections.

You can override this behavior in your `.env` if needed:

```
PDFMERGER_VERIFY_SSL=false  # Force disable SSL verification
```

**Security Notes:**

- URL downloads are enabled by default but can be disabled via configuration
- SSL certificate verification is **automatically managed based on environment** (`local` vs `production`)
- SSL verification is **always disabled in local environments** for developer convenience
- SSL verification is **always enabled in production** for security (unless explicitly overridden)
- Downloaded files are stored in temporary storage and automatically cleaned up
- Consider disabling URL support (`allow_urls => false`) in security-sensitive environments
- Only use URLs from trusted sources to prevent potential security risks

### Output Methods

[](#output-methods)

```
$merger = PDFMerger::make()
    ->addPDF($file1)
    ->addPDF($file2)
    ->merge();

// Save to disk
$merger->save('output.pdf');
$merger->saveAs('output.pdf');  // Alias

// Download in browser
return $merger->download();

// Stream to browser
return $merger->stream();

// Get as Response object
return $merger->toResponse();

// Get raw PDF content
$content = $merger->output();

// Get as base64 encoded string
$base64 = $merger->toBase64();
```

### Method Aliases for Better Readability

[](#method-aliases-for-better-readability)

```
PDFMerger::make()
    ->add($file)           // Alias for addPDF()
    ->addFile($file)       // Alias for addPDF()
    ->addAll($file)        // Shorthand for addPDF($file, 'all')
    ->merge()
    ->save();
```

### Adding Multiple Files at Once

[](#adding-multiple-files-at-once)

```
$files = [
    ['path' => '/path/to/file1.pdf', 'pages' => [1, 2]],
    ['path' => '/path/to/file2.pdf', 'pages' => 'all'],
    ['path' => '/path/to/file3.pdf', 'pages' => [1]],
];

PDFMerger::make()
    ->addMany($files)
    ->merge()
    ->save();
```

### Conditional Operations

[](#conditional-operations)

```
$merger = PDFMerger::make()
    ->when($condition, fn($m) => $m->addPDF($file))
    ->unless($otherCondition, fn($m) => $m->duplex(true))
    ->merge();
```

### Using Tap for Side Effects

[](#using-tap-for-side-effects)

```
PDFMerger::make()
    ->addPDF($file1)
    ->tap(fn() => logger('Added first file'))
    ->addPDF($file2)
    ->tap(fn() => logger('Added second file'))
    ->merge()
    ->save();
```

### Setting Custom Filename

[](#setting-custom-filename)

```
PDFMerger::make()
    ->setFileName('my-merged-document.pdf')
    ->addPDF($file1)
    ->addPDF($file2)
    ->merge()
    ->save();  // Will use 'my-merged-document.pdf' as filename
```

### Resetting the Merger

[](#resetting-the-merger)

```
$merger = PDFMerger::make()
    ->addPDF($file1)
    ->merge()
    ->save('first.pdf');

// Reset and reuse
$merger->reset()
    ->addPDF($file2)
    ->merge()
    ->save('second.pdf');
```

Error Handling
--------------

[](#error-handling)

The package throws specific exceptions for different error scenarios:

```
use StitchDigital\PDFMerger\Exceptions\PDFNotFoundException;
use StitchDigital\PDFMerger\Exceptions\InvalidPagesException;
use StitchDigital\PDFMerger\Exceptions\PDFMergeException;

try {
    PDFMerger::make()
        ->addPDF('/path/to/file.pdf')
        ->merge()
        ->save();
} catch (PDFNotFoundException $e) {
    // File not found or URL download failed
    // Examples:
    // - "Could not locate PDF file at '/path/to/file.pdf'"
    // - "Could not download PDF from 'https://example.com/file.pdf': Connection timeout"
    // - "URL downloads are disabled in configuration"
} catch (InvalidPagesException $e) {
    // Invalid pages parameter
} catch (PDFMergeException $e) {
    // General merge error
}
```

Configuration
-------------

[](#configuration)

The published configuration file (`config/pdfmerger.php`) allows you to customize:

- **temp\_path**: Directory for temporary files
- **output\_path**: Default output directory
- **orientation**: Default page orientation ('P' or 'L')
- **duplex**: Enable duplex mode by default
- **memory\_limit**: Memory limit for large files (in MB)
- **allow\_urls**: Enable/disable URL downloads (default: `true`)
- **url\_download\_timeout**: Timeout for URL downloads in seconds (default: `30`)
- **url\_verify\_ssl**: Verify SSL certificates for HTTPS URLs (default: `true`)
- **disk**: Default Storage disk for integration

Extending with Macros
---------------------

[](#extending-with-macros)

You can extend the package with custom methods using macros:

```
use StitchDigital\PDFMerger\PDFMerger;

PDFMerger::macro('addDirectory', function ($directory) {
    foreach (glob($directory . '/*.pdf') as $file) {
        $this->addPDF($file);
    }
    return $this;
});

// Usage
PDFMerger::make()
    ->addDirectory('/path/to/pdfs')
    ->merge()
    ->save();
```

Upgrading from v1.x
-------------------

[](#upgrading-from-v1x)

See [UPGRADING.md](UPGRADING.md) for detailed upgrade instructions.

### Key Breaking Changes

[](#key-breaking-changes)

- Minimum PHP version is now 8.2
- Minimum Laravel version is now 9.0
- `init()` is deprecated, use `make()` instead
- `merge()` now returns `self` instead of `void` for chaining
- Hungarian notation removed from internal properties

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

Run with coverage:

```
composer test-coverage
```

Code Quality
------------

[](#code-quality)

Check code style:

```
composer format-check
```

Fix code style:

```
composer format
```

Run static analysis:

```
composer analyse
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review our [security policy](SECURITY.md) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Stitch Digital](https://github.com/stitch-digital) - Current Maintainer
- [Webklex](https://github.com/webklex) - Original Author
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance85

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 60% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

5

Last Release

154d ago

Major Versions

1.0.0 → 2.0.02026-01-23

PHP version history (2 changes)1.0.0PHP &gt;=5.5.9

2.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/1afc3eb4b0906148c94893fc2c76a6832d3c5f6499f6f9ab223ec6d945ee95da?d=identicon)[johntrickett](/maintainers/johntrickett)

---

Top Contributors

[![Webklex](https://avatars.githubusercontent.com/u/2884144?v=4)](https://github.com/Webklex "Webklex (18 commits)")[![laraben](https://avatars.githubusercontent.com/u/34068668?v=4)](https://github.com/laraben "laraben (3 commits)")[![johntrickett86](https://avatars.githubusercontent.com/u/149476912?v=4)](https://github.com/johntrickett86 "johntrickett86 (2 commits)")[![hasanwijaya](https://avatars.githubusercontent.com/u/46978559?v=4)](https://github.com/hasanwijaya "hasanwijaya (2 commits)")[![warksit](https://avatars.githubusercontent.com/u/5296633?v=4)](https://github.com/warksit "warksit (1 commits)")[![KreutzerCode](https://avatars.githubusercontent.com/u/53813841?v=4)](https://github.com/KreutzerCode "KreutzerCode (1 commits)")[![Jason-Toh](https://avatars.githubusercontent.com/u/69843506?v=4)](https://github.com/Jason-Toh "Jason-Toh (1 commits)")[![apocsve](https://avatars.githubusercontent.com/u/3503460?v=4)](https://github.com/apocsve "apocsve (1 commits)")[![maddhatter](https://avatars.githubusercontent.com/u/4449339?v=4)](https://github.com/maddhatter "maddhatter (1 commits)")

---

Tags

laravelpdfLaravel pdfmergerpdfmergerpdf mergestitch-digital

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/stitch-digital-laravel-pdfmerger/health.svg)

```
[![Health](https://phpackages.com/badges/stitch-digital-laravel-pdfmerger/health.svg)](https://phpackages.com/packages/stitch-digital-laravel-pdfmerger)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[webklex/laravel-pdfmerger

Generic PDF merger for Laravel

1422.9M2](/packages/webklex-laravel-pdfmerger)[laravel/ai

The official AI SDK for Laravel.

9782.1M162](/packages/laravel-ai)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
