Để dùng Memcached cache toàn bộ HTML của trang WordPress (Full Page Cache) — tức là không chạy tới bất kỳ xử lý WordPress/PHP/MySQL nào (bỏ qua query SQL), bạn cần viết một layer cache ngoài WordPress hoặc dùng một plugin hỗ trợ, nhưng ở đây mình sẽ hướng dẫn bạn tự viết bằng PHP tích hợp Memcached, gắn vào wp-config.php hoặc đầu tiên của index.php.


✅ Mục tiêu:

  • Nếu trang đã được cache → trả HTML luôn, không chạy WordPress.
  • Nếu chưa có → chạy WordPress bình thường, sau đó lưu HTML vào Memcached.

✅ 1. Tạo file page-cache.php, đặt tại wp-content/page-cache.php hoặc chỗ nào bạn muốn:

<?php
// Khởi tạo Memcached
$mem = new Memcached();
$mem->addServer('127.0.0.1', 11211);

// Bỏ qua cache nếu:
// - Không phải GET
// - Trong admin, ajax, REST API, preview, tìm kiếm, đã đăng nhập
if (
    $_SERVER['REQUEST_METHOD'] !== 'GET' ||
    defined('DOING_AJAX') ||
    strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false ||
    strpos($_SERVER['REQUEST_URI'], '/feed') !== false ||
    strpos($_SERVER['REQUEST_URI'], '?s=') !== false ||
    isset($_GET['preview']) ||
    isset($_COOKIE['wordpress_logged_in']) ||
    preg_grep('/^wordpress_sec_/', array_keys($_COOKIE))
) {
    return;
}

// Chuẩn hóa cache key từ đường dẫn
$request_uri = $_SERVER['REQUEST_URI'];
$parsed = parse_url($request_uri);
$cache_key = 'fullpage_' . md5($parsed['path']);

// Nếu có sẵn cache → xuất ra ngay
$cached = $mem->get($cache_key);

if ($cached !== false) {
    header('X-Cache: HIT');
    echo $cached;
    exit;
}

// Bắt đầu ghi bộ đệm output
ob_start(function($buffer) use ($mem, $cache_key) {
    if (
        http_response_code() === 200 &&
        strpos($buffer, 'wp-admin-bar') === false // tránh cache admin bar
    ) {
        $mem->set($cache_key, $buffer, 300); // cache 5 phút
        header('X-Cache: MISS - Cached');
    } else {
        header('X-Cache: MISS - Not cached');
    }
    return $buffer;
});

✅ 2. Nhúng page-cache.php vào đầu index.php của WordPress

Ngay dòng đầu của index.php (trước require __DIR__ . '/wp-blog-header.php';):

require_once __DIR__ . '/wp-content/page-cache.php';

✅ 3. Xử lý loại trừ cache

Bạn có thể loại trừ các trường hợp:

  • POST request
  • Trang admin
  • Người đăng nhập
  • AJAX, feed, REST API

Cập nhật điều kiện trong page-cache.php:

// Bỏ qua cache nếu:
// - Không phải GET
// - Trong admin, ajax, REST API, preview, tìm kiếm, đã đăng nhập
if (
    $_SERVER['REQUEST_METHOD'] !== 'GET' ||
    defined('DOING_AJAX') ||
    strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false ||
    strpos($_SERVER['REQUEST_URI'], '/feed') !== false ||
    strpos($_SERVER['REQUEST_URI'], '?s=') !== false ||
    isset($_GET['preview']) ||
    isset($_COOKIE['wordpress_logged_in']) ||
    preg_grep('/^wordpress_sec_/', array_keys($_COOKIE))
) {
    return;
}

✅ 4. Xóa cache khi cần

Khi cập nhật bài viết hoặc comment, bạn có thể dùng hook save_post hay comment_post để xóa cache theo URL:

add_action('save_post', function($post_ID) {
    $url = get_permalink($post_ID);
    $key = 'fullpage_' . md5(parse_url($url, PHP_URL_PATH));
    $mem = new Memcached();
    $mem->addServer('127.0.0.1', 11211);
    $mem->delete($key);
});

✅ Kết quả:

Tình huốngHành động
Trang có trong MemcachedTrả HTML luôn, không load WordPress
Trang chưa cóLoad WP, tạo HTML, lưu cache
Người đăng nhập / POST / AjaxBỏ qua cache, load WP bình thường

⚠️ Lưu ý:

  • Không nên cache trang /wp-admin/, REST API, các form.
  • Nên xóa cache theo URL khi bài viết hoặc comment được cập nhật.
  • Có thể dùng thêm plugin như "WP Super Cache" hoặc "Batcache" nếu bạn không muốn viết tay.