eslam-abass/laravel-invoice-generator
Generate customizable PDF invoices in Laravel using publishable Blade templates. Supports dynamic line items, taxes/discounts, currency and localization, optional QR code links, config-driven branding, and easy preview/PDF output via facade.
Installation:
composer require eslam-abass/laravel-invoice-generator
php artisan vendor:publish --provider="EslamAbass\InvoiceGenerator\InvoiceServiceProvider"
This publishes the default config (config/invoice.php) and Blade template (resources/views/vendor/invoice/template.blade.php).
First Use Case: Generate a basic invoice in a controller:
use EslamAbass\InvoiceGenerator\Facades\Invoice;
$invoiceData = [
'customer' => ['name' => 'Client Co.', 'email' => 'client@example.com'],
'items' => [['description' => 'Service', 'quantity' => 1, 'price' => 100]],
];
$pdf = Invoice::make($invoiceData)->toPdf();
return $pdf->stream('invoice.pdf');
Key Files to Inspect:
config/invoice.php: Default settings (currency, tax rules, branding).resources/views/vendor/invoice/template.blade.php: Default Blade template (customize this for branding).Data Structure: Always pass an associative array with these keys:
$data = [
'customer' => ['name', 'address', 'email', 'phone'], // Required
'company' => ['name', 'address', 'logo_path'], // Optional (uses config defaults if omitted)
'items' => [ // Array of items
['description', 'quantity', 'price', 'tax_rate' => 0],
],
'notes' => 'Optional notes', // Optional
'qr_code_url' => 'https://example.com/invoice/1', // Optional
];
Generating Invoices:
Invoice::make($data)->toPdf()->stream('invoice.pdf');
Invoice::make($data)->preview();
$path = Invoice::make($data)->save('invoices/invoice_' . time() . '.pdf');
Dynamic Data: Use Blade directives in the template to dynamically render data:
@foreach($invoice->items as $item)
<tr>
<td>{{ $item->description }}</td>
<td>{{ $item->quantity }}</td>
<td>{{ number_format($item->price, 2) }}</td>
</tr>
@endforeach
Multi-Language Support:
Pass a locale key in the data array or set it globally in the config:
$data = ['locale' => 'ar', ...];
// or in config/invoice.php: 'default_locale' => 'ar'
Tax and Discounts:
Define tax rules in config/invoice.php:
'tax_rules' => [
'default' => 10, // 10% tax
'special' => 5, // Custom tax rate
],
Apply discounts in the data:
$data = [
'discount' => 5, // 5% discount
'items' => [...],
];
QR Codes: Enable via config:
'qr_code' => [
'enabled' => true,
'logo_path' => 'path/to/logo.png',
],
Pass a URL in the data:
$data = ['qr_code_url' => 'https://app.example.com/invoices/123'];
Laravel Mail: Attach the PDF to an email:
Mail::send([], [], function ($message) use ($pdf) {
$message->subject('Your Invoice');
$message->attach($pdf->getPath(), ['as' => 'invoice.pdf']);
});
Laravel Storage: Save invoices to disk:
$path = Invoice::make($data)->save('invoices/' . $invoiceId . '.pdf');
API Responses: Return the PDF as a downloadable file:
return Invoice::make($data)->toPdf()->download('invoice.pdf');
Custom Templates:
Create a new Blade template in resources/views/invoices/custom.blade.php and specify it:
Invoice::make($data)->setTemplate('invoices.custom')->toPdf();
Template Paths:
resources/views/.resources/views/vendor/invoice/template.blade.php. Override this by publishing a custom template first.Logo Paths:
storage/app/public/logos/company.png) or relative to the public folder (e.g., logos/company.png). Use public_path() in your code to resolve paths:
$data['company']['logo_path'] = public_path('logos/company.png');
Currency Formatting:
number_format() under the hood. For non-standard formatting (e.g., commas vs. spaces), override the formatCurrency() method in a custom service provider or extend the package.QR Code Generation:
endroid/qr-code package. If missing, install it manually:
composer require endroid/qr-code
Tax Calculations:
tax_rate is specified. For complex tax rules (e.g., VAT tiers), extend the TaxCalculator class or override the calculateTax() method.Locale Conflicts:
locale key in the data matches a valid locale supported by PHP’s intl extension. Test with:
setlocale(LC_ALL, $data['locale']);
Preview Before PDF:
Use the preview() method to debug the Blade template in the browser:
Invoice::make($data)->preview();
Log Data: Add a temporary debug step to log the data being passed:
\Log::info('Invoice Data', $data);
Check Published Files: Verify the config and template were published correctly:
php artisan vendor:publish --tag=invoice-config
php artisan vendor:publish --tag=invoice-views
Custom Invoice Class:
Extend the base Invoice class to add methods:
namespace App\Services;
use EslamAbass\InvoiceGenerator\Invoice as BaseInvoice;
class CustomInvoice extends BaseInvoice {
public function addFooter($text) {
$this->data['footer'] = $text;
return $this;
}
}
Bind it in a service provider:
$this->app->bind('invoice', function () {
return new CustomInvoice();
});
Override Tax Logic:
Publish the config and extend the tax_rules array:
'tax_rules' => [
'default' => 10,
'books' => 5, // Custom tax rate for books
],
Then modify the template to apply per-item tax rates:
@foreach($invoice->items as $item)
<td>{{ $item->tax_rate }}%</td>
@endforeach
Add Custom Fields: Extend the data structure and template:
$data = [
'customer' => [...],
'custom_fields' => ['due_date' => '2023-12-31'],
];
Add to the template:
@if(isset($invoice->custom_fields->due_date))
Due Date: {{ $invoice->custom_fields->due_date }}
@endif
Hooks for Post-Generation: Use Laravel’s events to act after invoice generation. Extend the package to dispatch events:
// In a service provider
Invoice::make($data)->toPdf()->save($path);
event(new InvoiceGenerated($data, $path));
Cache Templates: If generating many invoices, cache the compiled Blade template:
Invoice::make($data)->setTemplate('invoices.custom')->cacheTemplate()->toPdf();
Batch Processing: For bulk invoices, queue the generation:
Invoice::make($data)->toPdf()->queue(function ($pdf) {
$pdf->save("invoices/{$invoiceId}.pdf");
});
How can I help you explore Laravel packages today?