Why Use Dompdf for PDF Generation in CodeIgniter 4?
Dompdf stands out as one of the most popular choices for developers working in CodeIgniter 4 environments due to its simplicity, flexibility, and strong compatibility with modern web standards. Unlike heavier alternatives such as mPDF or TCPDF, which can require extensive configuration, Dompdf allows you to leverage your existing HTML/CSS skills — write clean, responsive templates using familiar tools like Bootstrap or Tailwind, then render them as pixel-perfect PDFs. It supports most CSS3 features (including floats, tables, and basic media queries), making it ideal for dynamic, data-driven documents pulled from your MySQL database.Key benefits include zero external dependencies after Composer installation, lightweight footprint for faster performance, easy inline styling to avoid layout issues, and seamless integration via a simple controller method. For e-commerce sites, admin panels, or SaaS platforms built on CodeIgniter 4, Dompdf saves development time by eliminating the need to learn proprietary PDF syntax. It also handles Unicode characters well (with font adjustments), supports images (local or base64-encoded), and works reliably in shared hosting environments where tools like wkhtmltopdf may not be available. In short, if you're looking for a balance of ease, reliability, and customization when generating PDFs from HTML views in CodeIgniter 4, Dompdf delivers professional results with minimal overhead — making it the go-to solution for most PHP developers in 2025–2026.

Table Of Content
1 Prerequisites
- PHP 8.1+ (CodeIgniter 4 recommends 8.2+ as of 2025/2026)
- Composer installed globally
- MySQL database access
- Basic knowledge of CodeIgniter 4 (controllers, models, views, migrations)
2 Introduction
3 Create / Install a Codeigniter 4 Project
3.1 Install Codeigniter 4 Project
Use the following command to install a new CodeIgniter project:
composer create-project codeigniter4/appstarter ci-4-dompdf-app
Then, navigate to your project directory:
cd ci-4-dompdf-app
3.2 Configure Environment and MySql Database
# CI_ENVIRONMENT = production
CI_ENVIRONMENT = development
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ci4_pdf
DB_USERNAME=root
DB_PASSWORD=
Create the database ci4_pdf in MySQL (e.g., via phpMyAdmin or CLI: CREATE DATABASE ci4_pdf;). 4 Install Dompdf via Composer
composer require dompdf/dompdf
This adds the latest stable Dompdf (v2.x+ as of 2025/2026), which supports modern CSS better than older versions.
5 Create A Model and Migration
php spark make:model OrderModel
Edit app/Models/OrderModel.php to configure fields for managing order data.
<?php
namespace App\Models;
use CodeIgniter\Model;
class OrderModel extends Model
{
protected $table = 'orders';
protected $primaryKey = 'id';
protected $allowedFields = ['customer_name', 'total_amount', 'created_at'];
protected $useTimestamps = true;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
}
Create a migration file for the orders table:
php spark make:migration AddOrders
Edit the migration file to define the table structure:
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddOrders extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 5,
'unsigned' => true,
'auto_increment' => true,
],
'customer_name' => [
'type' => 'VARCHAR',
'constraint' => '100',
],
'total_amount' => [
'type' => 'DECIMAL',
'constraint' => '10,2',
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('orders');
}
public function down()
{
$this->forge->dropTable('orders');
}
}
Set up a migration for the Order Items table and a model to manage the data.
php spark make:model OrderItemModel
Edit app/Models/OrderItemModel.php to configure fields for managing order data.
<?php
namespace App\Models;
use CodeIgniter\Model;
class OrderItemModel extends Model
{
protected $table = 'order_items';
protected $primaryKey = 'id';
protected $allowedFields = ['order_id', 'product_name', 'quantity', 'price'];
}
Create a migration file for the order items table:
php spark make:migration AddOrderItems
Edit the migration file to define the table structure:
<?php
forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 5,
'unsigned' => true,
'auto_increment' => true,
],
'order_id' => [
'type' => 'INT',
'constraint' => 5,
'unsigned' => true,
],
'product_name' => [
'type' => 'VARCHAR',
'constraint' => '100',
],
'quantity' => [
'type' => 'INT',
'constraint' => 5,
],
'price' => [
'type' => 'DECIMAL',
'constraint' => '10,2',
],
]);
$this->forge->addKey('id', true);
$this->forge->addForeignKey('order_id', 'orders', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('order_items');
}
public function down()
{
$this->forge->dropTable('order_items');
}
}
Run the migration:
php spark migrate
6 Create Seeder for Sample Data
<?php
namespace App\Database\Seeds;
use CodeIgniter\Database\Seeder;
use CodeIgniter\I18n\Time;
class OrderSeeder extends Seeder
{
public function run()
{
$data = [
[
'customer_name' => 'John Doe',
'total_amount' => 150.00,
'created_at' => Time::now(),
],
[
'customer_name' => 'Jane Smith',
'total_amount' => 200.50,
'created_at' => Time::now(),
],
];
$this->db->table('orders')->insertBatch($data);
$items = [
[
'order_id' => 1,
'product_name' => 'Product A',
'quantity' => 2,
'price' => 50.00,
],
[
'order_id' => 1,
'product_name' => 'Product B',
'quantity' => 1,
'price' => 50.00,
],
[
'order_id' => 2,
'product_name' => 'Product C',
'quantity' => 3,
'price' => 66.83,
],
];
$this->db->table('order_items')->insertBatch($items);
}
}
?>
7 Create Controller
php spark make:controller InvoiceController
Add methods for generating PDF:
<?php
namespace App\Controllers;
use App\Models\OrderModel;
use App\Models\OrderItemModel;
use CodeIgniter\Controller;
use Dompdf\Dompdf;
class InvoiceController extends Controller
{
public function index()
{
$orderModel = new OrderModel();
$data['orders'] = $orderModel->findAll();
return view('orders/index', $data);
}
public function generate($id)
{
$orderModel = new OrderModel();
$itemModel = new OrderItemModel();
$order = $orderModel->find($id);
if (!$order) {
return redirect()->to('/orders')->with('error', 'Order not found');
}
$data['order'] = $order;
$data['items'] = $itemModel->where('order_id', $id)->findAll();
$html = view('invoices/invoice', $data);
$dompdf = new Dompdf();
$options = $dompdf->getOptions();
$options->set('isRemoteEnabled', true); // Enable if using external resources
$options->set('defaultFont', 'DejaVu Sans'); // For better font support
$dompdf->setOptions($options);
$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
// Stream PDF inline (preview in browser); use Attachment => true for download
$dompdf->stream('invoice_' . $id . '.pdf', ['Attachment' => false]);
}
}
?>
8 Create View Files
app/Views/orders/index.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Orders List</title>
<style>
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
</style>
</head>
<body>
<h1>Orders</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Customer</th>
<th>Total</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<tr>
<td><?= esc($order['id']) ?></td>
<td><?= esc($order['customer_name']) ?></td>
<td>$<?= number_format($order['total_amount'], 2) ?></td>
<td><a href="<?= site_url('invoice/generate/' . $order['id']) ?>">Generate PDF</a></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</body>
</html>
app/Views/invoices/invoice.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Invoice #<?= $order['id'] ?></title>
<style>
body { font-family: DejaVu Sans, sans-serif; margin: 20px; }
h1 { text-align: center; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #000; padding: 10px; text-align: left; }
.total { text-align: right; font-weight: bold; margin-top: 20px; }
</style>
</head>
<body>
<h1>Invoice #<?= esc($order['id']) ?></h1>
<p><strong>Customer:</strong> <?= esc($order['customer_name']) ?></p>
<p><strong>Date:</strong> <?= esc($order['created_at']) ?></p>
<table>
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($items as $item): ?>
<tr>
<td><?= esc($item['product_name']) ?></td>
<td><?= esc($item['quantity']) ?></td>
<td>$<?= number_format($item['price'], 2) ?></td>
<td>$<?= number_format($item['quantity'] * $item['price'], 2) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="total">Grand Total: $<?= number_format($order['total_amount'], 2) ?></p>
</body>
</html>
9 Define a Route
use CodeIgniter\Router\RouteCollection;
$routes->get('orders', 'InvoiceController::index');
$routes->get('invoice/generate/(:num)', 'InvoiceController::generate/$1');
10 Folder Structure
11 Run and Test
php spark serve
Visit http://localhost:8080/orders in your browser. You should see the orders list. Click "Generate PDF" for an order to preview the PDF inline.
Troubleshooting
- Blank PDF? Ensure HTML is valid; check PHP error logs.
- Fonts/Images Issues? Dompdf supports basic CSS; use base64 for images if needed.
- Errors? Verify database connection and run composer dump-autoload if classes aren't found.
This code is tested in a standard CI4 setup and should work fully. If you encounter issues, provide error details!
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
Run the command `composer require dompdf/dompdf` in your CodeIgniter 4 project directory.
You need PHP 8.2 or higher, Composer, and MySQL database.
Load the HTML view, create a new Dompdf instance, load the HTML, set paper size if needed, render it, and use `$dompdf->stream('filename.pdf', ['Attachment' => false]);` to display inline.
This often happens due to output buffering issues, incorrect headers, or HTML layout errors (e.g., wrong table colspan). Ensure no extra output before streaming and validate your HTML/CSS for Dompdf compatibility.
Common causes include PHP version differences, folder/write permissions, memory limits, or server configuration (e.g., output buffering or headers). Check error logs, ensure writable folders, and increase memory_limit if needed.
Dompdf has limited CSS support (CSS 2.1 mostly, some CSS3). Images work if paths are absolute or base_path is set. JavaScript is not supported at all.
Use inline CSS or internal <style> tags in the view file. Avoid advanced CSS features; stick to basics like tables, margins, fonts, and colors for reliable rendering.
Use `php spark serve` and access the app at http://localhost:8080.
