laraveldaily/laravel-invoices
Generate customizable PDF invoices in Laravel with templates, translations, taxes/discounts/shipping, due dates, serial numbers, and flexible currency formatting. Store, download, or stream via any configured filesystem, with global settings and per-invoice overrides.
Installation:
composer require laraveldaily/laravel-invoices:^4.1.1
php artisan invoices:install
This publishes assets, views, translations, and config.
First Use Case: Generate a basic invoice with a single item:
use LaravelDaily\Invoices\Invoice;
use LaravelDaily\Invoices\Classes\Buyer;
use LaravelDaily\Invoices\Classes\InvoiceItem;
$invoice = Invoice::make()
->buyer(new Buyer(['name' => 'John Doe']))
->addItem(InvoiceItem::make('Service')->pricePerUnit(10.99))
->stream();
config/invoices.php (overrides defaults like currency, serial numbers, seller details).resources/views/vendor/invoices/templates/default.blade.php (customize invoice layout).Invoice::make() for quick instantiation (alternative to class instantiation).Define Parties:
$seller = Invoice::makeParty(['name' => 'Your Company']);
$buyer = Invoice::makeParty(['name' => 'Client', 'email' => 'client@example.com']);
Create Items:
$item = InvoiceItem::make('Consulting')
->pricePerUnit(150)
->quantity(2)
->taxByPercent(10);
Build Invoice:
$invoice = Invoice::make()
->seller($seller)
->buyer($buyer)
->addItems([$item, $item2])
->taxRate(5)
->discountByPercent(5)
->save('public'); // Save to disk
Deliver Invoice:
return $invoice->stream(); // Open in browser
// OR
return $invoice->download(); // Force download
currencySymbol('$')).template('custom') to switch layouts.getAmountInWords() for currency spelling (e.g., getAmountInWords(100, 'es')).foreach ($orders as $order) {
$invoice = Invoice::make()
->buyer($order->customer)
->addItems($order->items)
->save('public');
// Send email with $invoice->url()
}
save($disk) to store invoices in S3, local, etc. Retrieve with url().Storage::disk('public')->get($invoice->filename).return response()->json(['invoice_url' => $invoice->url()]);
Template Paths:
resources/views/vendor/invoices/templates/.php artisan invoices:update after updates may break templates.Serial Number Conflicts:
sequence_padding (5) may cause gaps if sequences aren’t sequential. Adjust or use a database-backed sequence.Currency Formatting:
currencyFormat uses tags {VALUE}, {SYMBOL}, {CODE}. Misplaced tags (e.g., {SYMBOL}{VALUE} vs {VALUE} {SYMBOL}) can break alignment.Logo Issues:
logo() must be absolute (e.g., public_path('images/logo.png')). Use getLogo() in templates to avoid path problems.Tax/Discount Calculations:
totalTaxes() or totalDiscount(), ensure they match calculated values to avoid discrepancies.toHtml() to debug template rendering before PDF generation.currencySymbol()) take precedence over config.dd($invoice->getSerialNumber()) to debug formatting issues.php artisan invoices:update to reset templates if changes aren’t reflecting.Custom Party Classes:
Extend LaravelDaily\Invoices\Classes\Party to add fields (e.g., taxId):
class CustomBuyer extends Party {
public function taxId() { return $this->custom_fields['tax_id'] ?? null; }
}
Update config:
'buyer' => ['class' => App\Models\CustomBuyer::class],
Dynamic Templates: Use Blade directives to conditionally render sections:
@if($invoice->getCustomData('is_recurring'))
<div>Recurring Invoice</div>
@endif
Hooks:
Override methods like getTotalAmount() to add custom logic (e.g., loyalty discounts):
$invoice->setCustomData(['loyalty_discount' => 10]);
// In a custom class:
public function getTotalAmount() {
$baseTotal = parent::getTotalAmount();
return $baseTotal - ($baseTotal * ($this->getCustomData('loyalty_discount') ?? 0) / 100);
}
Localization:
Add translations for custom fields in resources/lang/{locale}/invoices.php:
return [
'custom_fields' => [
'tax_id' => 'Tax ID',
],
];
stream() in Loops: Generate PDFs in bulk, then stream/download.How can I help you explore Laravel packages today?