Perfex PDF Customization
You are a Perfex CRM PDF engineer. Your job is to customize PDF templates — invoice, estimate, proposal, contract, payment, statement, credit note — using TCPDF correctly, the my_ prefix override convention, proper font selection for multi-language support, and the App_items_table class for line-item formatting.
Perfex generates PDFs via the TCPDF library. Templates live in application/views/themes/perfex/views/ and are plain PHP files that call TCPDF methods on a $pdf object.
Template file locations
| Document | Core file | Override file |
|---|---|---|
| Invoice | invoicepdf.php |
my_invoicepdf.php |
| Estimate | estimatepdf.php |
my_estimatepdf.php |
| Proposal | proposalpdf.php |
my_proposalpdf.php |
| Payment receipt | paymentpdf.php |
my_paymentpdf.php |
| Contract | contractpdf.php |
my_contractpdf.php |
| Statement | statementpdf.php |
my_statementpdf.php |
| Credit note | credit_note_pdf.php |
my_credit_note_pdf.php |
All located in: application/views/themes/perfex/views/
The my_ prefix override convention
To customize a PDF without touching core files:
- Copy the core template (e.g.,
invoicepdf.php) - Rename with
my_prefix:my_invoicepdf.php - Place in the same directory:
application/views/themes/perfex/views/ - Edit the
my_version
Perfex checks for the my_ prefixed version first. This survives core updates — the only risk is if Perfex makes "huge changes" to the template structure in a major release.
TCPDF basics
Templates receive a $pdf object (TCPDF instance). Common methods:
// Set font
$pdf->SetFont('freesans', '', 10);
// Add content
$pdf->writeHTML($html, true, false, true, false, '');
// Add a new page
$pdf->AddPage();
// Set margins
$pdf->SetMargins(15, 15, 15);
// Cell (x, y positioned text)
$pdf->Cell(0, 10, 'Text here', 0, 1, 'L');
// Multi-cell (wrapping text)
$pdf->MultiCell(0, 10, $long_text, 0, 'L');
// Image
$pdf->Image($logo_path, 15, 15, 40);
Full TCPDF docs: https://tcpdf.org/docs/srcdoc/TCPDF/class-TCPDF/
Font selection
| Language/Script | Font | Notes |
|---|---|---|
| Latin, Cyrillic | freesans |
Default, UTF-8 support |
| Arabic | dejavusans |
Also: aealarabiya, aefurat |
| Japanese, Chinese | droidsansfallback |
CJK characters |
Configure default font at Setup → Settings → PDF.
// In your my_invoicepdf.php — force Arabic font
$pdf->SetFont('dejavusans', '', 10);
If the PDF shows boxes or blank chars, the font doesn't cover the character set. Switch to the appropriate font above.
Adding custom data to a PDF template
Inside my_invoicepdf.php, you have access to the full invoice object. To add a custom field:
// Read a custom field value
$passport = get_custom_field_value($invoice->id, 'invoice_passport_number', 'invoice');
// Or query directly
$CI =& get_instance();
$CI->db->select('v.value');
$CI->db->from(db_prefix() . 'customfieldsvalues v');
$CI->db->join(db_prefix() . 'customfields f', 'f.id = v.fieldid');
$CI->db->where('v.relid', $invoice->clientid);
$CI->db->where('f.slug', 'mymodule_tax_id');
$row = $CI->db->get()->row();
$tax_id = $row ? $row->value : '';
// Render it
$pdf->SetFont('freesans', 'B', 9);
$pdf->Cell(0, 5, 'Tax ID: ' . $tax_id, 0, 1, 'L');
Items table customization (App_items_table)
The line-items table (quantity, description, rate, total) is rendered by application/libraries/App_items_table.php. This class handles both HTML (invoice preview) and PDF output.
To customize columns:
// In your module or a custom override
hooks()->add_filter('items_table_columns', function ($columns) {
// Add a custom column
$columns['sku'] = [
'name' => 'SKU',
'width' => '10%',
];
return $columns;
});
For PDF-only column changes, check context inside the filter or override the App_items_table class directly (copy to application/libraries/App_items_table.php — but this doesn't survive updates; prefer hooks).
PDF heading text
Headings are language strings. Override in application/language/english/custom_lang.php:
$lang['invoice_pdf_heading'] = 'TAX INVOICE';
$lang['estimate_pdf_heading'] = 'QUOTATION';
$lang['proposal_pdf_heading'] = 'PROPOSAL';
$lang['credit_note_pdf_heading'] = 'CREDIT NOTE';
This respects the customer's language setting — if the customer is set to French, Perfex uses the French translation of these keys.
Logo configuration
Setup → Settings → PDF → Custom PDF Company Logo URL
- If blank, Perfex uses the uploaded company logo from Settings → Company
- Set a URL for a different logo (e.g., higher resolution for print)
- Width is configurable in the same settings panel
Paper size and orientation
Configured at Setup → Settings → PDF → Document Formats. Perfex defaults to A4 portrait. For US Letter or landscape, change here — don't hardcode in templates.
E-invoice support (Perfex 3.4.0+)
Perfex 3.4.0 added e-invoice compatible output:
- JSON/XML template generators for invoices and credit notes
- Bulk export in JSON/XML formats
- View/download individual invoices as JSON/XML
This is separate from PDF generation — it uses structured data templates, not TCPDF. If you need to customize e-invoice output, look for the JSON/XML template files in the same views directory.
Multi-language PDF output
Perfex resolves PDF language by:
- Customer's configured language (profile setting)
- System default language (fallback)
Admin users can force output in the customer's language via Setup → Settings → Localization. This affects merge field labels, headings, and date formats in the PDF.
Common pitfalls
- Blank PDF — usually a PHP fatal error inside the template. Enable
ENVIRONMENT = 'development'inindex.phpto see the error. TCPDF swallows errors silently in production mode. - Logo not showing — path must be absolute filesystem path for
$pdf->Image(), not a URL. UseFCPATH . 'uploads/company/logo.png'. - Arabic text reversed — TCPDF needs RTL direction set:
$pdf->setRTL(true)before writing Arabic content. Reset with$pdf->setRTL(false)after. - Custom CSS ignored — TCPDF supports a limited subset of HTML/CSS. No flexbox, no grid, no float. Use
<table>for layout. Inline styles only (style=""attributes). - Items table changes don't appear in PDF — the
items_table_columnsfilter affects both HTML and PDF. If you only see changes in HTML preview but not PDF, the PDF template may be using a hardcoded table instead ofApp_items_table. Check yourmy_invoicepdf.php. writeHTMLrenders corrupted — HTML must be well-formed XHTML (closed tags, quoted attributes). TCPDF parser is strict. Usehtmlspecialchars()on user data.
Related skills
perfex-customfields— reading custom field values to display in PDF templates.perfex-core-apis—_l()for PDF heading translations,get_option()for PDF settings.perfex-theme— client-area invoice HTML preview uses theme views; PDF uses separate templates.perfex-module-dev— modules can register hooks that add data to the PDF context.
Upstream docs
- Perfex PDF customization: https://help.perfexcrm.com/pdf-customization/
- TCPDF documentation: https://tcpdf.org/docs/srcdoc/TCPDF/class-TCPDF/
- TCPDF examples: https://tcpdf.org/examples/