sander-van-hooft/laravel-invoicable
Installation
composer require sander-van-hooft/laravel-invoicable
php artisan vendor:publish --provider="SanderVanHooft\Invoicable\InvoicableServiceProvider" --tag="migrations"
php artisan migrate
Publish config (optional):
php artisan vendor:publish --provider="SanderVanHooft\Invoicable\InvoicableServiceProvider" --tag="config"
First Use Case: Create an Invoicable Model
Extend your Eloquent model with SanderVanHooft\Invoicable\Traits\Invoicable and define invoiceable relationships:
use SanderVanHooft\Invoicable\Traits\Invoicable;
class Order extends Model
{
use Invoicable;
public function invoice()
{
return $this->hasOne(Invoice::class);
}
}
Generate an Invoice
$order = Order::find(1);
$invoice = $order->createInvoice(); // Creates a concept invoice
Add Invoice Lines
$invoice->lines()->create([
'description' => 'Product 1',
'quantity' => 2,
'unit_price' => 10.00,
]);
Send Invoice via Email
$invoice->send(); // Uses default email template
$invoice = Invoice::find(1);
$invoice->markAsDraft(); // Transition status
$invoice->markAsSent();
Use createLine() or addLine() for dynamic invoicing:
$invoice->addLine([
'description' => 'Service Fee',
'quantity' => 1,
'unit_price' => $serviceFee,
'tax_rate' => 21, // Optional tax rate
]);
Schedule recurring invoices via events or queues:
$invoice = $subscription->createInvoice();
$invoice->setRecurring(true)
->setRecurrence('monthly')
->setNextDueDate(now()->addMonth());
Publish and override Blade templates:
php artisan vendor:publish --provider="SanderVanHooft\Invoicable\InvoicableServiceProvider" --tag="views"
Modify resources/views/vendor/invoicable/invoice.blade.php.
Generate PDFs on-demand:
$pdf = $invoice->download(); // Returns a PDF response
// OR save to storage:
$invoice->saveAsPdf('path/to/invoice.pdf');
Use events to sync invoices with payment gateways:
Invoice::created(function (Invoice $invoice) {
if ($invoice->isPaid()) {
event(new InvoicePaid($invoice));
}
});
Create API routes for invoice management:
Route::get('/invoices/{invoice}', [InvoiceController::class, 'show']);
Route::post('/invoices/{invoice}/send', [InvoiceController::class, 'send']);
Extend notifications for custom logic:
use SanderVanHooft\Invoicable\Notifications\InvoiceSent;
InvoiceSent::toMailUsing(function ($notifiable, $notification) {
return (new MailMessage)
->subject('Custom Subject')
->line('Custom content');
});
Override locale in config or dynamically:
$invoice->setLocale('en_US'); // Per-invoice override
Use factories and assertions:
$invoice = Invoice::factory()->create();
$invoice->assertStatus('concept');
$invoice->assertLinesCount(1);
invoice_lines table schema.--force:
php artisan migrate:fresh --force
tax_rate is set on lines or use setTaxRate() on the invoice:
$invoice->setTaxRate(21); // Applies to all lines
composer require barryvdh/laravel-dompdf).concept → paid).$invoice->markAsDraft(); // Valid: concept → draft
$invoice->markAsSent(); // Valid: draft → sent
config(['invoicable.locale' => 'en_US']);
Dump invoice data for debugging:
\Log::info('Invoice data:', $invoice->toArray());
Listen for invoice events to debug lifecycle:
Invoice::created(fn ($invoice) => \Log::debug('Invoice created:', $invoice->id));
Ensure line items meet requirements:
$line = $invoice->lines()->create([...]);
$line->validate(); // Throws exception if invalid
Generate PDFs locally before deployment:
$pdf = $invoice->download();
Storage::disk('local')->put('test.pdf', $pdf->output());
Extend the Invoice model:
class CustomInvoice extends \SanderVanHooft\Invoicable\Models\Invoice
{
protected $casts = [
'custom_field' => 'boolean',
];
}
Add custom fields to invoice_lines:
$invoice->lines()->create([
'description' => 'Custom Line',
'custom_data' => json_encode(['key' => 'value']),
]);
Use model events:
Invoice::created(function (Invoice $invoice) {
// Add custom logic (e.g., update order status)
});
Replace the PDF driver:
$invoice->setPdfDriver('snappy'); // Requires `barryvdh/laravel-snappy`
Extend line item validation:
use SanderVanHooft\Invoicable\Rules\InvoiceLine;
$validator = Validator::make($data, [
'unit_price' => ['required', new InvoiceLine],
]);
How can I help you explore Laravel packages today?