Modifying timthumb.php in wordpress’s theme for optimize performance

ปรกติแล้วใน timthumb.php จะมีความสามารถในการ cache รูปที่ถูกย่ออยู่แล้ว เพื่อไม่ให้มันต้อง crop รูปสำหรับทุกๆ request. แต่ว่าปัญหา คือ ไฟล์ cache ของ timthumb นั้น มันไม่ใช่ไฟล์รูปที่สามารถเปิดดูได้โดยตรง เพราะว่าที่ส่วนหัวของ cache จะมี filePrependSecurityBlock แทรกอยู่เพื่อป้องกันการส่งสคริปท์ php เข้าไปรัน. จากลักษณะการทำงานที่เป็นชี้นี้ ทำให้เราไม่สามารถใช้พวก Reverse proxy หรือ CDN มาช่วยในการลดโหลดได้ของ WordPress ที่มีจำนวน Traffic สูงๆ ได้ (ไม่งั้นมันเรียก php ขึ้นมาทำงานตลอด).

โดยปรกติแล้ว Theme ของ WordPress ที่มีการใช้ timthumb กัน เค้าจะเรียกใช้งาน timthumb ด้วย URL ลักษณะนี้

'/scripts/timthumb.php?src='.$image.'&w='.$width.'&h='.$height.'&zc=1'

สิ่งที่เรากำลังจะพยายามแก้ไข คือ

  1. แก้ไฟล์ timthumb.php
    1. แก้การตั้งชื่อไฟล์ cache ของ timthumb ให้มีการระบุ นามสกุล ของไฟล์ภาพไว้ในชื่อด้วย
    2. แก้ไม่ให้ timthumb เขียน filePrependSecurityBlock ลงในไฟล์ cache
  2. แก้ไฟล์ functions.php
    1. แก้ตรงส่วน HTML ในการแสดงภาพ timthumb ให้ไปเรียกที่ไฟล์ cache โดยตรง

ข้อเสียของการทำเช่นนี้ คือ เราจะเสียความสามารถของ timthumb ในส่วนของ expired cache ไป แต่มันก็ไม่ได้มีความจำเป็นใดๆ เลยกับลักษณะการใช้งานในบล็อค WordPress ส่วนใหญ่.

1.1) แก้การตั้งชื่อไฟล์ cache

  • กำหนด constant FILE_CACHE_SUFFIX ให้เป็น empty string
  • ใน __construct ให้ดูตรงบรรทัดที่มีการกำหนดค่า $this->cachefile ตรงโค๊ดบล็อคนั้น มันจะมี if($this->isURL){ อยู่ (เวอร์ชั่นขณะที่เขียนบทความนี้ คือ 2.8.11) ให้เราแก้ตรง else { ของบล็อคนั้น เพราะว่าเราจะแก้เฉพาะการเรียก crop ภาพจากภายในเท่านั้น. เติม code นี้เข้าไปด้านใน else ตรงล่างสุด
    if(count($_GET)==4 && isset($_GET['src']) && isset($_GET['w']) && isset($_GET['h']) && $_GET['zc']) {
    $this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->localImage. $this->localImageMTime) . basename($this->localImage);
     }

1.2) ปิดการใช้ filePrependSecurityBlock

  • ผมแก้ตรงฟังก์ชั่น serveCacheFile โดยใส่ code นี้ เพื่อให้มัน return ค่าแต่แรกเลย (จริงๆ การทำแบบนี้น่าจะก่อให้เกิด error ในบางเคสนะเนี่ย)
    echo file_get_contents ($this->cachefile); return true;

2) แก้ functions.php ของ theme ที่ใช้

จริงๆ แล้วตรงนี้จะไม่จำเป็นต้องมาแก้นะ ถ้าคุณสามารถที่จะแก้การตั้งชื่อไฟล์ให้แบบว่าอ่านออก แล้วใช้ .htaccess ของ apache หรือ rewrite ของ nginx ในการเขียน rule เพื่อ rewrite URL with Query String  ไปยัง URL ที่เป็น static file แทนเลย.

สำหรับการแก้ไฟล์ functions.php ให้ลองเสิร์ซหาคำว่า timthumb.php ในไฟล์ดู คุณจะเจอบรรทัดที่มันสร้าง HTML ส่วนของ <img /> ที่ใช้ timthumb.php

สิ่งที่คุณต้องทำ คือ เช็คว่าไฟล์ภาพนั้นๆ มันมีไฟล์ cache ของ timthumb หรือยัง  ถ้ามีแล้ว ก็ส่งเป็น src ที่เป็น URL ไปยัง static file ดังกล่าวเลย. แต่ถ้ายังไม่มีก็ return src ไปตามปรกติ เพื่อไปเรียก timthumb.php สร้างไฟล์ cache ขึ้นมาให้เราก่อน

เสร็จแล้ว เย่ !