Trong PHP vốn đã chạy nhanh nay còn có thêm cơ chế cache làm cho ngôn ngữ PHP ngày càng hoàn hảo. Tôi nhắc đến cơ chế cache vì các hàm ob_start(), ob_get_contents(), ob_clean(), ob_end_flush() sẽ hỗ trợ chúng ta trong quá trình thực hiện cơ chế này.

Tôi có 1 ví dụ đơn giản như sau:

ob_start();
echo "Hieu.dev. ";
echo "From e-web.vn";
$content1 = ob_get_contents();
ob_clean();
ob_end_flush();
echo $content1; // Hieu.dev. From e-web.vn
 
ob_start();
echo "The quick brown fox Jumps over the lazy dog.";
$content2 = ob_get_contents();
ob_clean();
ob_end_flush();
 
echo $content2; // The quick brown fox Jumps over the lazy dog.

Như ví dụ ta thấy mọi kết xuất bắt đầu từ ob_start(); đến ob_clean(); đều được hàm ob_get_contents(); lưu vào biến $content.

Cơ chế cache là gì?
– Client sẽ gửi Request tới Server bước này thì không tốn thời gian.
– Tiếp đó server sẽ Parse Request, gửi truy vấn tới Database , và lấy dữ liệu từ Database trả về
– Parse dữ liệu và trả lại cho Browser

=> Việc query tới DataBase sẽ tốn rất nhiều thời gian, thêm nữa dữ liệu Response thường lớn, đây chính là nguyên nhân làm cho ứng dụng của ta chậm đi.
Vì sao phải tạo cache?
– Tạo cache sẽ giúp cho site chạy nhanh và giảm truy cập trực tiếp vào database
– Với php việc tạo cache chỉ ở mức genarate ra file, thường là dạng HTML
Đây là giải pháp rất hay nếu làm tốt, có thể tăng tốc độ lướt web lên hàng chục lần. Tuỳ vào mục đích của ứng dụng để cache, cũng như kết hợp các phương pháp cho hiệu quả:

1. Cache toàn bộ page: Nguyên cả page ứng với url nhất định được lưu vào cache, các truy cập tiếp theo đến cùng url này sẽ include ngay lập tức file cache được tạo ra trước đó, do đó sẽ giảm tối đa về thời gian do server không phải xử lý gì cả (kể cả truy cập DataBase). Cách này đơn giản nhưng không linh hoạt, và khó thực thi vì dữ liệu trên các trang là dữ liệu động.

2. Cache từng phần của page: Ta sẽ chỉ cache một phần của page mà tại đó dữ liệu ít bị thay đổi. Điều này đảm bảo client sẽ nhận được dữ liệu trả về là chính xác mà không phải dữ liệu cũ từ file cache.

3. Cache SQL: Khi cùng câu lệnh SQL được gọi đi gọi lại, thì chỉ lệnh đầu tiên được gửi đến DataBase server, trong các Framework đều có cache SQL.

Để bắt đầu thì ta phải tạo một thư mục cache để chứa các file cache cho ứng dụng của ta, không lên để các file cache lung tung, tránh cache file không được CHMOD đúng quyền read & write. Do đó để dễ chmod và bảo mật ta cần tạo riêng thư mục cache, việc đặt cache key cũng cần chú ý để dễ phân biệt.
Sau đây là một ví dụ đơn giản cache dữ liệu:

Ví dụ sau sẽ tạo ra cache file $cacheFile có nhiệm vụ như sau:
– Lưu data vào file với thời gian $time_update_cache
– Trong thời gian này, PHP không truy vấn xuống Database mà chỉ sử dụng nội dung được get từ $cacheFile. Do không truy vấn nên sẽ giảm thời gian đáng kể.
– Nếu không tìm thấy $cacheFile hoặc quá thời gian $time_update_cache thì PHP sẽ thực hiện truy vấn SQL, lấy data push vào $cacheFile

Cứ như vậy, tiến trình lập đi lập lại.

$cacheFile = 'cache/name_file_cache.php'; 
$time_update_cache = 600; // milisecond(s)
// Kiểm tra cache file tồn tại và đã đến lúc cập nhật lại cache file hay chưa?
if ( (file_exists($cacheFile)) 
    && (time() <= (fileatime($cacheFile) + $time_update_cache) ))
{ 
    // Nếu thỏa thì đọc nội dung trong cache file 1 cách nhanh chóng
    $content = file_get_contents($cacheFile); 
    // Xuất kết quả
    echo $content; 
} 
else // Cập nhật cache file
{ 
    ob_start(); 
    // Chỗ này có thể truy vấn Database và xuất ra ngay kết quả 
    // => tất cả đều lưu vào biến $content
    echo '<h1>Hello world to cache</h1>'; 
    echo '<h2>Hieu.dev - e-web.vn</h2>';
    $content = ob_get_contents(); 
    ob_end_clean(); 
    // Ghi cache file
    file_put_contents($cacheFile,$content); 
    // Xuất kết quả
    echo $content; 
} 

Một ví dụ khác, cache dữ liệu SQL:

// text file cache
$file = 'sql_cache.html';
 
$expire = 86400; // 24 hours 
 
// Nếu có cache file và còn trong thời gian chưa hết $expire
if (file_exists($file) && 
    filemtime($file) > (time() - $expire))
{ 
    // Uunserialize data từ cache file
    $records = unserialize(file_get_contents($file)); 
} 
else // Cập nhật cache file
{ 
    $link = mysql_connect('localhost','username','password') or die (mysql_error()); 
    mysql_select_db('shop') or die (mysql_error()); 
    /* form SQL query */ 
    $query = "SELECT * FROM categories"; 
    $result = mysql_query($query) or die (mysql_error());
    while ($record = mysql_fetch_array($result) )
    { 
        $records[] = $record; 
    } 
    // Serialize data và push vào cache file
    $OUTPUT = serialize($records); 
    $fp = fopen($file,"w"); 
    fputs($fp, $OUTPUT); 
    fclose($fp); 
} // end else 
 
// Query results are in $records array 
foreach ($records as $id=>$row) 
{ 
    if ($row['category_id'] == $_REQUEST['category_id']) 
    { 
        // Loại sản phẩm đã được lưu trong cache file
        echo $row['category_name']; 
    } 
    else { 
        // Loại sản phẩm mới, chưa được lưu trong cache file
        // Lúc này ta kiểm tra trong Database xem có loại sản phẩm này hay ko?
        // Nếu có thì thực hiện cập nhật lại cache file
        // Nếu không thì thông báo lỗi không tìm thấy
        echo $row['category_name'];
    } 
} // end foreach 

sql_cache.html sẽ có dạng:

a:1:{i:0;a:6:{i:0;s:1:"1";s:11:"category_id";s:1:"1";i:1;s:9:"Computers";s:13:"category_name";s:9:
"Computers" ;i:2;s:25:"Description for computers";s:20:"category_description" 
;s:25:"Description for computers";}} 

Giải thích thêm: unserialize() là hàm ngược với serialize(). serialize() có tác dụng mã hóa 1 đối tượng, hay kiểu dữ liệu nào đó thành dạng như nội dung sql_cache.html ở trên. unserialize() sẽ biến nội dung mã hóa thành chính object mà trước khi ta serialize().

Với ví dụ trên thì ta thấy cache file được nhìn thấy rất rõ, những data nào ít được cập nhật ta nên dùng cơ chế cache để load giúp PHP load nhanh hơn. Tùy từng trường hợp mà bạn sử dụng cache cho đúng.