baidouabdellah/laravel-arpdf

Generate Arabic-friendly PDFs in Laravel with a driver-based architecture (mPDF by default)

Maintainers

Package info

github.com/baidou5/laravel-arpdf

pkg:composer/baidouabdellah/laravel-arpdf

Statistics

Installs: 328

Dependents: 0

Suggesters: 0

Stars: 6

Open Issues: 0

3.0.0 2026-03-06 15:27 UTC

This package is auto-updated.

Last update: 2026-03-06 15:29:01 UTC


README

ArPDF Logo

Laravel ArPDF

Arabic-first PDF generation for Laravel, rebuilt from scratch on top of mPDF.

laravel-arpdf is designed for production-grade Arabic documents (invoices, contracts, reports) with stable RTL rendering, Arabic shaping, and robust font handling.

Why This Is Stronger Than Dompdf

  • Native mPDF engine focused on complex scripts (Arabic/RTL)
  • Better Arabic glyph shaping and bidirectional text handling
  • Reliable custom font loading and fallback strategy
  • Rich PDF controls: metadata, margins, header/footer, watermark

Core Features

  • Full Arabic + RTL + UTF-8 support
  • Fluent Laravel API
  • Custom Arabic fonts via config map
  • stream, download, save, and raw string output
  • Header / footer HTML
  • Text or image watermark
  • Metadata API (title, author, subject, keywords, creator)
  • Reusable document profiles (profile('invoice_ar'))
  • Named templates with variable interpolation
  • Layouts and reusable components for templates
  • Report Builder DSL for business reports
  • File queue pipeline for deferred rendering
  • Laravel queue pipeline (dispatch / dispatchSync)
  • Plugin API (before/after render hooks)
  • Plugin marketplace with named built-ins (watermark_text, signature_block, quick_qr, certificate_signature)
  • Snapshot testing workflow for PDF regression checks
  • PDF render cache for repeated documents

Installation

composer require baidouabdellah/laravel-arpdf

Publish config and fonts (optional but recommended):

php artisan vendor:publish --provider="Baidouabdellah\LaravelArpdf\ArPDFServiceProvider"

Quick Example

use ArPDF;

public function invoice()
{
    return ArPDF::direction('rtl')
        ->title('فاتورة')
        ->author('My Company')
        ->header('<div style="text-align:right">رأس الصفحة</div>')
        ->footer('<div style="text-align:center">{PAGENO}</div>')
        ->watermarkText('سري')
        ->loadView('pdf.invoice', ['title' => 'فاتورة'])
        ->download('invoice.pdf');
}

Production Features

ArPDF::profile('invoice_ar')
    ->registerTemplate('invoice_basic', '<h1>{{ title }}</h1><p>{{ customer.name }}</p>')
    ->loadTemplate('invoice_basic', [
        'title' => 'فاتورة',
        'customer' => ['name' => 'أحمد'],
    ])
    ->useCache(true, 3600)
    ->download('invoice.pdf');

Layouts, Components, Reports, Queue

$pdf = app(\Baidouabdellah\LaravelArpdf\ArPDF::class);

$pdf->registerLayout('base', '<html><body>{{ section:header }}{{ content }}{{ component:footer }}</body></html>')
    ->registerComponent('footer', '<footer>{{ company }}</footer>')
    ->registerTemplate('invoice', \"@layout('base')\\n@section('header')<h1>{{ title }}</h1>@endsection\\n<p>{{ customer.name }}</p>\")
    ->loadTemplate('invoice', [
        'title' => 'فاتورة',
        'customer' => ['name' => 'أحمد'],
        'components' => ['footer' => ['company' => 'My Co']],
    ]);

$pdf->report(function ($r) {
    $r->heading('تقرير شهري')->table(['البند', 'القيمة'], [['المبيعات', 15000]]);
});

$pipeline = $pdf->queuePipeline(); // file-based queue
$jobId = $pipeline->enqueue($pdf, storage_path('app/reports/monthly.pdf'));
$pipeline->processNext();

$pdf->laravelQueuePipeline()->dispatchSync($pdf, storage_path('app/reports/sync.pdf'));

Plugins & Snapshots

use Baidouabdellah\LaravelArpdf\Contracts\PdfPlugin;

class FooterPlugin implements PdfPlugin {
    public function beforeRender($pdf, string $html, array $options): array {
        return ['html' => $html . '<footer>Signed</footer>', 'options' => $options];
    }
    public function afterRender($pdf, string $binary, array $context): string {
        return $binary;
    }
}

$pdf->usePlugin(new FooterPlugin())->loadHTML('<h1>Doc</h1>');

$pdf->usePluginNamed('watermark_text', ['text' => 'CONFIDENTIAL', 'alpha' => 0.15])
    ->usePluginNamed('signature_block', ['signer' => 'Admin', 'title' => 'CTO'])
    ->usePluginNamed('quick_qr', ['text' => 'INV-1001', 'size' => 90]) // offline QR
    ->loadHTML('<h1>Invoice</h1>');

$pdf->usePluginNamed('certificate_signature', [
    'private_key' => storage_path('keys/private.pem'),
    'certificate' => storage_path('keys/cert.pem'),
    'sidecar_path' => storage_path('app/signatures/invoice.sig.json'),
]);

$check = \Baidouabdellah\LaravelArpdf\ArPDF::verifySignature(
    storage_path('app/invoices/invoice.pdf'),
    storage_path('app/signatures/invoice.sig.json'),
    storage_path('keys/cert.pem')
);

// Artisan command
// php artisan arpdf:verify-signature storage/app/invoices/invoice.pdf storage/app/signatures/invoice.sig.json --cert=storage/keys/cert.pem

$result = $pdf->assertSnapshot('doc-v1'); // stores/compares sha256 snapshot
if (! $result['matched']) {
    // regression detected
}

Output Destinations

output($filename, $dest) supports:

  • Legacy: I, D, F, S
  • Named: inline, download, file, string

Configuration

Main options in config/arpdf.php:

  • direction, default_font, fonts_path, fonts
  • paper, orientation, margins
  • metadata
  • mpdf (native mPDF overrides)

Testing

vendor/bin/phpunit -c tests/phpunit.xml

License

MIT