Why Generate PDF Invoices in Laravel 11 Using Dompdf?
In modern web applications built with Laravel 11, delivering professional-looking invoices to customers is essential for e-commerce platforms, freelance billing systems, SaaS dashboards, and any business that handles orders or payments. Generating PDF invoices ensures consistent formatting across devices, prevents tampering, enables easy printing or emailing, and provides a polished client experience that boosts trust and perceived professionalism.Dompdf remains one of the most popular and reliable choices for Laravel developers because it seamlessly converts HTML (and Blade templates) into PDFs without requiring external services like cloud APIs. The barryvdh/laravel-dompdf wrapper makes integration effortless — you get full control over styling with CSS, support for images/logos, tables for line items, totals with taxes/discounts, and even custom headers/footers. Unlike heavier alternatives (e.g., Browsershot or mPDF), Dompdf is lightweight, server-side only, requires zero Node.js dependencies, and performs well on shared hosting or VPS environments.
Whether you're building a simple order system or scaling a full invoicing module, this approach saves development time while delivering pixel-perfect, downloadable documents. In this complete step-by-step tutorial, you'll learn exactly how to set up Dompdf in Laravel 11, create dynamic invoice data from your database, design a clean Blade template, and trigger instant PDF downloads — all with production-ready best practices.
By the end, you'll have a reusable invoice generator ready for real-world use, helping you streamline billing workflows and improve user satisfaction.

Table Of Content
1 Prerequisites
- PHP 8.2+
- Composer
- MySQL (or preferred DB) Basic knowledge of Laravel migrations, Blade, and Eloquent
2 Introduction
Let’s get started and turn your Laravel 11 app into a powerful invoicing machine!
3 Create / Install a Laravel Project
3.1 Install Laravel Project
composer create-project laravel/laravel laravel11-dompdf-app
Then navigate to your project:
cd laravel11-dompdf-app
3.2 Configure MySql Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel11
DB_USERNAME=root
DB_PASSWORD=
4 Install Barryvdh/Laravel-Dompdf
composer require barryvdh/laravel-dompdf
(Optional but recommended): Publish the config for custom settings like paper size or fonts:
php artisan vendor:publish --provider="Barryvdh\DomPDF\ServiceProvider"
5 Create Models & Migrations for Orders
php artisan make:migration create_order_table
Add the following fields:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('order', function (Blueprint $table) {
$table->id();
$table->string('order_ref');
$table->string('order_invoice');
$table->string('customer_first_name');
$table->string('customer_last_name');
$table->string('customer_address');
$table->string('customer_company');
$table->string('amount');
$table->string('order_status');
$table->timestamps();
});
Schema::create('orderitems', function (Blueprint $table) {
$table->id();
$table->string('order_id');
$table->string('product_name');
$table->string('item_price');
$table->string('quantity');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('order');
Schema::dropIfExists('orderitems');
}
};
Run the migration:
php artisan migrate
Create the Order model in app/Models/Order.php:
php artisan make:model Order
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'orders';
}
Create the OrderItem model in app/Models/OrderItem.php:
php artisan make:model OrderItem
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class OrderItem extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'orderitems';
}
6 Build the PDF Controller
php artisan make:controller PdfController
This Laravel 11 code defines a PdfController that handles displaying orders and generating invoices as PDF files. Let’s go through it step by step.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Order;
use App\Models\OrderItem;
use PDF;
class PdfController extends Controller
{
public function index()
{
$orders = Order::get();
return view('index',compact('orders'));
}
public function invoice($id)
{
$order = Order::find($id);
$orderitems = OrderItem::where('order_id', $id)->get();
$pdf = PDF::loadView('invoice', compact('order', 'orderitems'))
->setPaper('a4', 'portrait');
return $pdf->download('invoice.pdf');
}
}
?>
Let’s break this code into pieces and explain what is happening.
- namespace App\Http\Controllers;: This defines that the PdfController belongs to the App\Http\Controllers namespace.
- use App\Models\Order;: Imports the Order model to interact with the orders table in the database.
- use App\Models\Orderitem;: Imports the Orderitem model, which likely represents individual items in an order.
- use PDF;: Imports Laravel's PDF package (likely barryvdh/laravel-dompdf) for generating PDF documents.
- Retrieves all records from the orders table using Order::get().
- Passes the $orders data to the index view using compact('orders'), allowing the view to display the list of orders.
- Retrieves the order details using Order::find($id).
- Fetches the items related to that order using Orderitem::where('order_id', $id)->get().
- Calls PDF::loadView('invoice', compact('order', 'orderitems')); to generate a PDF using the invoice Blade view.
- Returns the generated PDF for download as invoice.pdf.
7 Define a Route
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PdfController;
Route::get('/', function () {
return view('welcome');
});
Route::get('orders', [PdfController::class, 'index']);
Route::get('invoicepdf/{id}', [PdfController::class, 'invoice']);
8 Create Blade Views (Order List + Invoice Template)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DataTables with Laravel 11</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/dataTables.bootstrap5.min.js"></script>
</head>
<body>
<div class="container">
<h1>Order List</h1>
<table id="orderTable" class="table table-bordered ">
<thead>
<tr>
<th scope="col">Order Ref</th>
<th scope="col" class="text-right">Amount</th>
<th scope="col" class="text-right">Order Status</th>
<th scope="col" class="text-right">Download Invoice</th>
</tr>
</thead>
<tbody>
@foreach($orders as $order)
<tr>
<td>{{ $order->order_ref }}</td>
<td>{{ $order->amount }}</td>
<td>{{ $order->order_status }}</td>
<td>
<a target="_blank"
title="Generate Invoice"
href="invoicepdf/{{ $order->id }} ">
{{ $order->order_invoice }}
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<script>
$(document).ready(function() {
$('#orderTable').DataTable({});
});
</script>
</body>
</html>
Invoice Template (invoice.blade.php)
<!DOCTYPE html>
<html>
<head>
<title>Generate Dynamic PDFs in Laravel with DomPDF - GetSampleCode.com</title>
<style>
.table-bordered {
border: 1px solid #ccc;
border-spacing: 0px;
}
.table-bordered td,
.table-bordered th {
border: 1px solid #ccc;
padding:5px;
}
@page {
margin: 100px 25px;
}
header {
position: fixed;
top: -60px;
left: 0px;
right: 0px;
height: 50px;
font-size: 20px !important;
background-color: #000;
color: white;
text-align: center;
line-height: 35px;
}
footer {
position: fixed;
bottom: -60px;
left: 0px;
right: 0px;
height: 50px;
font-size: 20px !important;
background-color: #000;
color: white;
text-align: center;
line-height: 35px;
}
footer:after {
content:"Page No - " counter(page);
}
</style>
</head>
<body>
<header>
Welcome to Get Sample Code
</header>
<!-- Define Footer Block -->
<footer>
</footer>
<div style="font-size:24px; color:'#dddddd'; text-align:center "><i>Invoice</i></div>
<hr>
<table class="table" width="100%">
<tr>
<td><b>Invoice:</b> # {{ $order->order_invoice }}</td>
<td><b>Receiver:</b></td>
</tr>
<tr>
<td><b>Date:</b> {{ \Carbon\Carbon::parse($order->order_at)->format('Y-m-d') }} </td>
<td>{{ $order->customer_first_name }} {{ $order->customer_last_name }} <br> {{ $order->customer_company }}</td>
</tr>
<tr>
<td></td>
<td >{{ $order->customer_address }}</td>
</tr>
</table>
<hr>
<table class="table table-bordered table-striped" width="100%" >
<thead>
<tr>
<th>Item Description</th>
<th>Price ($)</th>
<th>Quantity</th>
<th>Subtotal ($)</th>
</tr>
</thead>
@php($total = 0);
@foreach($orderitems as $item)
@php($price = $item->item_price*$item->quantity)
@php($total += $price)
<tr>
<td>{{ $item->product_name }}</td>
<td>{{ number_format($item->item_price, 2) }}</td>
<td>{{ $item->quantity}}</td>
<td style="text-align:right;">{{ number_format($price, 2) }}</td>
</tr>
@endforeach
<tr>
<td colspan="3" style="text-align:right;">Total ($)</td>
<td style = "text-align:right;">{{ number_format($total, 2) }}</td>
</tr>
</table>
</body>
</html>
9 Folder Structure
10 Test & Generate Your First PDF Invoice
php artisan serve
Accessing Orders List:
- When visiting /orders (or the route mapped to PdfController@index), it displays all orders.
Generating Invoice PDF:
- When accessing /invoicepdf/{id}, it retrieves the order and its items and generates a downloadable invoice.pdf.
11 Best Practices & Tips
- Use inline CSS (Dompdf has limited external CSS support).
- Test complex layouts – Dompdf is great for simple invoices but consider Spatie/laravel-pdf (with Browsershot) for advanced CSS/JS.
- For large PDFs: Queue the generation with Laravel Jobs.
- Add images: Use absolute paths (public_path()).
- UTF-8 issues: Ensure <meta charset="utf-8"> and font support.
12 Conclusion
Written by Revathi M
PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel
Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.
Frequently Asked Questions
The barryvdh/laravel-dompdf package is used to convert HTML Blade views to PDF.
Run 'composer require barryvdh/laravel-dompdf'. The package is auto-discovered in Laravel 11.
Load the Blade view with data using PDF::loadView('invoice', compact('order', 'orderitems')), then return $pdf->download('invoice.pdf').
Use $pdf->stream('invoice.pdf') instead of $pdf->download().
Tables 'orders' (with order_ref, amount, etc.) and 'orderitems' (with product_name, item_price, quantity, etc.) are created via migrations.
Use internal CSS with @page for margins, inline styles, and simple tables. Page numbering can be added with CSS counters.
No, the barryvdh/laravel-dompdf package is auto-discovered in Laravel 11.
PHP 8.2 or higher, Composer, and a configured MySQL database.
