PDF Optimization Suggestions
April 17, 2025 Β· AI Conversations
function pdf_invoice_head($header, $order_id ){
//CHANGE DATE HERE AND BELOW y-m-d
$date2 = strtotime('2021-11-24');
$orderedDate = strtotime(get_post_meta($order_id,'_dispensed_date',TRUE ));
if($orderedDate < $date2 ){
$headers = '' . esc_html__('Medication details:', 'woocommerce-pdf-invoice') . '' .
'' .
'' .
'' .
'' . esc_html__( 'Medication', 'woocommerce-pdf-invoice' ) . '' .
'' . esc_html__( 'Quantity', 'woocommerce-pdf-invoice' ) . '' .
'' . esc_html__( 'Strength', 'woocommerce-pdf-invoice' ) . '' .
'' . esc_html__( 'Dosage', 'woocommerce-pdf-invoice' ) . '' .
'' .
'' .
'';
return $headers;
}
else{
$headers = '' . esc_html__('Medication details:', 'woocommerce-pdf-invoice') . '' .
'' .
'' .
'' .
'' . esc_html__( 'Medication', 'woocommerce-pdf-invoice' ) . '' .
'' . esc_html__( 'Dosage', 'woocommerce-pdf-invoice' ) . '' .
'' .
'' .
'';
return $headers;
}
}
add_filter('pdf_content_additional_content','woocommerce_pdf_invoice_new_labels',10,2);
function woocommerce_pdf_invoice_new_labels( $content , $order_id){
$sign_img ='';
$prescriber_id = get_post_meta($order_id,'_prescriber_id',true);
$user_info = get_userdata($prescriber_id);
$prescriber_name = isset($user_info->display_name) && $user_info->display_name!='' ? $user_info->display_name : $user_info->user_nicename;
$prescriber_sign = get_user_meta($prescriber_id,'prescriber_signature',true);
if($prescriber_sign){
$sign_url = wp_get_attachment_url($prescriber_sign);
$sign_url = str_replace(site_url('/'),'',$sign_url);
$sign_img ='';
}
$content = str_replace( '[[BILLING_FNAME]]', get_post_meta( $order_id,'_billing_first_name',TRUE ),$content);
$content = str_replace( '[[BILLING_LNAME]]', get_post_meta( $order_id,'_billing_last_name',TRUE ),$content);
$content = str_replace( '[[BILLING_DOB]]', get_post_meta( $order_id,'prescription_dob',TRUE ),$content);
// $content = str_replace( '[[ORDER_DATE]]', date('F j, Y',strtotime(get_post_meta( $order_id,'_completed_date',TRUE ))),$content);
$content = str_replace( '[[ORDER_DATE]]', date('F j, Y',strtotime(get_post_meta( $order_id,'_dispensed_date',TRUE ))),$content);
$content = str_replace( '[[MEDICATION_INFO]]',get_medication_details($order_id),$content);
$content = str_replace( '[[PRESCRIBER_NAME]]',$prescriber_name,$content);
$content = str_replace( '[[PRESCRIBER_REG_NUM]]',get_user_meta($prescriber_id,'prescriber_registration_number',true),$content);
$content = str_replace( '[[PRESCRIBER_SIGN]]',$sign_img,$content);
return $content;
}
function get_medication_details( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
// Check WC version – changes for WC 3.0.0
$pre_wc_30 = version_compare( WC_VERSION, '3.0', '
—
### π Identified Bottlenecks
1. **Repeated `get_post_meta()` calls**:
– You're fetching post meta (e.g., `_dispensed_date`, `prescription_dob`, `_billing_first_name`, etc.) multiple times per order.
– These are slow when run repeatedly inside loops.
2. **Multiple calls to `get_userdata()` and `get_user_meta()`**:
– Each call can be a separate query, especially when repeated for each order.
– This is inefficient in bulk generation.
3. **Creation of new `WC_Order` and `WC_Product_Variation` objects repeatedly**:
– These classes are heavy and cause slowdowns in loops.
4. **Uncached calls to `get_term_by()`**:
– Taxonomy term lookups for attributes like strength, quantity, etc., are repeated.
5. **PDF table output inside a loop**:
– Creating large HTML strings for many orders in a single execution can also stress memory and processing time.
—
### β Optimization Suggestions
#### β
1. Cache Meta Values per Order
Fetch all meta once and store in a local array:
$order_meta = get_post_meta($order_id);
$dispensed_date = isset($order_meta['_dispensed_date'][0]) ? strtotime($order_meta['_dispensed_date'][0]) : 0;
Use this `$order_meta` array everywhere instead of `get_post_meta()` calls.
#### β
2. Avoid Re-creating `WC_Product_Variation` in Each Loop
If you're calling:
$product_variation = new WC_Product_Variation($variation_id);
inside each loop, you should cache it if used repeatedly:
static $variation_cache = [];
if (!isset($variation_cache[$variation_id])) {
$variation_cache[$variation_id] = new WC_Product_Variation($variation_id);
}
$product_variation = $variation_cache[$variation_id];
#### β
3. Replace `get_term_by()` with Cached Version
Instead of calling `get_term_by()` every time:
static $term_cache = [];
$key = "{$attr_key}_{$attr}";
if (!isset($term_cache[$key])) {
$term_cache[$key] = get_term_by('slug', $attr, $attr_key);
}
$term = $term_cache[$key];
#### β
4. Minimize HTML String Concatenation
String concatenation in loops is expensive. Consider building arrays and then using `implode()`.
—
### π§ Bonus: Batch PDF Generation Strategy
If this is part of a bulk PDF generation for 50 orders at once:
– Offload it to a background job using **WP Cron** or **Action Scheduler**.
– Or paginate it in batches of 10β15 orders per run and combine later.
—
### π Summary of Key Improvements
| Area | Before | After |
|———————|——————————————-|——————————————|
| Meta access | `get_post_meta()` per key | One-time `get_post_meta()` per order |
| User data | Multiple `get_userdata()` calls | Cache `get_userdata()` per user |
| Variations | `new WC_Product_Variation()` per loop | Cache `WC_Product_Variation` object |
| Taxonomy terms | `get_term_by()` in loop | Static cache per key |
| Output buffer | Concatenate strings inside loop | Use arrays + `implode()` |
Would you like me to rewrite the key function with these performance enhancements applied?
—
### β Optimized Code
add_filter('pdf_template_table_headings','pdf_invoice_head',999,2);
function pdf_invoice_head($header, $order_id ){
$date2 = strtotime('2021-11-24');
$orderedDate = strtotime(get_post_meta($order_id, '_dispensed_date', true));
$heading = '<table border="0"><tr><th align="left"><h2>' . esc_html__('Medication details:', 'woocommerce-pdf-invoice') . '</h2></th></tr></table>';
if ($orderedDate < $date2) {
$headers = $heading .
'<table class="shop_table orderdetails" width="100%" id="mtab-2">
<thead><tr>
<th width="35%" align="left">' . esc_html__('Medication', 'woocommerce-pdf-invoice') . '</th>
<th width="10%" align="left">' . esc_html__('Quantity', 'woocommerce-pdf-invoice') . '</th>
<th width="20%" align="left">' . esc_html__('Strength', 'woocommerce-pdf-invoice') . '</th>
<th width="35%" align="left">' . esc_html__('Dosage', 'woocommerce-pdf-invoice') . '</th>
</tr></thead>
</table>';
} else {
$headers = $heading .
'<table class="shop_table orderdetails" width="100%" id="mtab-2">
<thead><tr>
<th width="50%" align="left">' . esc_html__('Medication', 'woocommerce-pdf-invoice') . '</th>
<th width="50%" align="left">' . esc_html__('Dosage', 'woocommerce-pdf-invoice') . '</th>
</tr></thead>
</table>';
}
return $headers;
}
add_filter('pdf_content_additional_content','woocommerce_pdf_invoice_new_labels',10,2);
function woocommerce_pdf_invoice_new_labels( $content , $order_id){
$meta = get_post_meta($order_id);
$billing_fname = $meta['_billing_first_name'][0] ?? '';
$billing_lname = $meta['_billing_last_name'][0] ?? '';
$dob = $meta['prescription_dob'][0] ?? '';
$dispensed_date = isset($meta['_dispensed_date'][0]) ? strtotime($meta['_dispensed_date'][0]) : '';
$order_date = $dispensed_date ? date('F j, Y', $dispensed_date) : '';
$sign_img = '';
$prescriber_id = $meta['_prescriber_id'][0] ?? '';
if ($prescriber_id) {
$user_info = get_userdata($prescriber_id);
$prescriber_name = $user_info->display_name ?? $user_info->user_nicename ?? '';
$prescriber_sign = get_user_meta($prescriber_id, 'prescriber_signature', true);
if ($prescriber_sign) {
$sign_url = wp_get_attachment_url($prescriber_sign);
$sign_url = str_replace(site_url('/'), '', $sign_url);
$sign_img = '<img src="'.ABSPATH.$sign_url.'">';
}
}
$content = str_replace([
'[[BILLING_FNAME]]',
'[[BILLING_LNAME]]',
'[[BILLING_DOB]]',
'[[ORDER_DATE]]',
'[[MEDICATION_INFO]]',
'[[PRESCRIBER_NAME]]',
'[[PRESCRIBER_REG_NUM]]',
'[[PRESCRIBER_SIGN]]'
], [
$billing_fname,
$billing_lname,
$dob,
$order_date,
get_medication_details($order_id),
$prescriber_name ?? '',
get_user_meta($prescriber_id, 'prescriber_registration_number', true),
$sign_img
], $content);
return $content;
}
function get_medication_details( $order_id ) {
$order = wc_get_order($order_id);
if (!$order) return '';
$meta = get_post_meta($order_id);
$dispensed_date = isset($meta['_dispensed_date'][0]) ? strtotime($meta['_dispensed_date'][0]) : 0;
$date2 = strtotime('2021-11-24');
$lines = [];
foreach ( $order->get_items() as $item ) {
$variation_id = $item->get_variation_id();
$product = $item->get_product();
if (!$variation_id || !$product) continue;
if ($dispensed_date < $date2) {
$lines[] = '<tr>
<td width="35%" align="left">' . esc_html($product->get_name()) . '</td>
<td width="10%" align="left">' . esc_html(pdf_get_attr_slug_to_title($variation_id, 'quantity')) . '</td>
<td width="20%" align="left">' . esc_html(pdf_get_attr_slug_to_title($variation_id, 'strength')) . '</td>
<td width="35%" align="left">' . esc_html(get_post_meta($variation_id, '_textarea', true)) . '</td>
</tr>';
} else {
$lines[] = '<tr>
<td width="50%" align="left">' . esc_html(get_post_meta($variation_id, '_titlearea', true)) . '</td>
<td width="50%" align="left">' . esc_html(get_post_meta($variation_id, '_textarea', true)) . '</td>
</tr>';
}
}
if (empty($lines)) return '';
$output = '<table width="100%" id="mtab-1"><tbody>' . implode('', $lines) . '</tbody></table>';
return apply_filters('pdf_template_line_output', $output, $order_id);
}
if (!function_exists('pdf_get_attr_slug_to_title')) {
function pdf_get_attr_slug_to_title($variation_id, $type){
static $variation_cache = [];
static $term_cache = [];
if (!isset($variation_cache[$variation_id])) {
$variation_cache[$variation_id] = new WC_Product_Variation($variation_id);
}
$product_variation = $variation_cache[$variation_id];
$attrs = $product_variation->get_attributes();
foreach ($attrs as $attr_key => $attr_value) {
if (strpos($attr_key, 'pa_') !== false && strtolower(str_replace('pa_', '', $attr_key)) == strtolower($type)) {
$key = "{$attr_key}_{$attr_value}";
if (!isset($term_cache[$key])) {
$term_cache[$key] = get_term_by('slug', $attr_value, $attr_key);
}
return $term_cache[$key]->name ?? $attr_value;
}
}
return '';
}
}
add_action('woocommerce_order_status_dispensing', 'track_prescriber', 999, 2);
function track_prescriber($order_id, $order){
$user_id = get_current_user_id();
update_post_meta($order_id, '_prescriber_id', $user_id);
}
—
### β Key Enhancements Summary
– Used `get_post_meta($order_id)` once and reused values.
– Cached:
– `WC_Product_Variation` objects
– `get_term_by()` results
– Used `implode()` instead of concatenating long HTML strings inside loops.
– Prevented unnecessary object instantiations inside loops.
Let me know if you want this wrapped in a plugin format or need lazy-loading via Ajax/cron job for heavy batch processing.
Hereβs how you can **cache `get_post_meta()` across multiple orders** efficiently:
—
### β Strategy: Preload Meta for All Orders Before Loop
If youβre looping through multiple orders (e.g., 50+), use something like this **before your main loop**:
$order_ids = [123, 124, 125, ...]; // your array of selected order IDs
$order_meta_cache = [];
foreach ($order_ids as $order_id) {
$order_meta_cache[$order_id] = get_post_meta($order_id);
}
Then inside your processing loop:
foreach ($order_ids as $order_id) {
$meta = $order_meta_cache[$order_id]; // cached result
$dispensed_date = isset($meta['_dispensed_date'][0]) ? strtotime($meta['_dispensed_date'][0]) : 0;
$billing_fname = $meta['_billing_first_name'][0] ?? '';
// ... and so on
}
—
### β Benefits
– Avoids **50+ queries per meta field** across orders.
– Reduces **database round-trips**, improving speed and memory efficiency.
– Works great for **custom PDF generators**, CSV exporters, and even WooCommerce bulk actions.
—
### π Replacing `get_post_meta()` in Your Existing Code
In your PDF hook (e.g., `woocommerce_pdf_invoice_new_labels()`), pass this `$order_meta_cache` array if your PDF generator allows passing external context.
If not, you can create a **global/static cache** that loads on first call:
function get_order_meta_cached($order_id) {
static $cache = [];
if (!isset($cache[$order_id])) {
$cache[$order_id] = get_post_meta($order_id);
}
return $cache[$order_id];
}
Then use it like:
$meta = get_order_meta_cached($order_id);
$dispensed_date = strtotime($meta['_dispensed_date'][0] ?? '');
—
Would you like a full PDF export loop refactored using this method for bulk `order_ids`? Or is this being triggered through a plugin like **WooCommerce PDF Invoices & Packing Slips** that handles orders in its own loop?