Hook và Action trong WordPress: Những Anti-pattern cần tránh

Hook (action, filter) là linh hồn của WordPress. Nhờ hệ thống hook mà theme/plugin có thể mở rộng tính năng rất dễ dàng. Tuy nhiên, lạm dụng hoặc đặt hook sai chỗ có thể gây ra lỗi hiệu năng, bug khó debug và xung đột. Bài viết này tổng hợp các anti-pattern phổ biến khi làm việc với hook trong WordPress, và cách viết chuẩn hơn.

Hook và Action trong WordPress: Những Anti-pattern cần tránh

1. Lạm dụng pre_get_posts

pre_get_posts cho phép bạn chỉnh sửa query chính. Đây là hook mạnh nhưng cũng dễ bị lạm dụng. Một số dev thêm quá nhiều điều kiện hoặc áp dụng với mọi request khiến toàn bộ site chậm đi.

<?php
// Sai: áp dụng cho tất cả query, kể cả admin và WP_Query phụ
add_action('pre_get_posts', function($q) {
    $q->set('posts_per_page', -1);
});

// Đúng: chỉ áp dụng cho main query ở frontend
add_action('pre_get_posts', function($q) {
    if ( ! is_admin() && $q->is_main_query() && is_category() ) {
        $q->set('posts_per_page', 20);
    }
});

2. Filter the_content quá nặng

Nhiều plugin/theme hook vào the_content để thêm shortcode, lazy load, quảng cáo… Nhưng filter này chạy mỗi lần render nội dung, kể cả trong vòng lặp archive. Nếu code trong filter chậm, nó sẽ nhân lên rất nhiều.

<?php
// Sai: query database trong the_content
add_filter('the_content', function($content) {
    global $wpdb;
    $extra = $wpdb->get_var("SELECT COUNT(*) FROM wp_posts");
    return $content . '<p>Total posts: ' . $extra . '</p>';
});

// Đúng: cache kết quả hoặc preload từ trước
add_filter('the_content', function($content) {
    $extra = wp_cache_get('total_posts');
    if ($extra === false) {
        $extra = wp_count_posts('post')->publish;
        wp_cache_set('total_posts', $extra);
    }
    return $content . '<p>Total posts: ' . $extra . '</p>';
});

3. Thêm hook trong vòng lặp

Đặt add_action hoặc add_filter bên trong vòng lặp hoặc bên trong callback sẽ khiến hook được thêm nhiều lần. Điều này làm callback chạy lặp, dẫn đến bug và chậm.

<?php
// Sai: hook được thêm mỗi lần chạy template
while ( have_posts() ) {
    the_post();
    add_filter('the_title', 'my_title_filter');
}

// Đúng: thêm hook ở init/plugin_loaded
add_filter('the_title', 'my_title_filter');

4. Không remove_filter khi cần

Đôi khi bạn chỉ muốn filter trong context nhất định. Nếu không remove_filter, filter sẽ áp dụng ở mọi nơi, gây lỗi không mong muốn.

<?php
// Sai: filter áp dụng toàn site
add_filter('the_content', 'my_temp_filter');

// Đúng: chỉ dùng tạm trong một đoạn code
add_filter('the_content', 'my_temp_filter');
echo apply_filters('the_content', $my_string);
remove_filter('the_content', 'my_temp_filter');

5. Không xác định ưu tiên hook

Mặc định hook chạy theo thứ tự thêm vào. Nếu bạn viết plugin/theme, hãy đặt priority rõ ràng để tránh xung đột. Ví dụ: priority thấp (5) để chạy trước, priority cao (999) để override.

<?php
// Chạy sớm để chuẩn hóa dữ liệu
add_filter('the_content', 'normalize_content', 5);

// Chạy muộn để thêm quảng cáo
add_filter('the_content', 'append_ads', 999);

6. Không kiểm tra điều kiện trước khi hook

Đôi khi bạn không cần hook cho mọi request (vd: REST API, admin). Thêm điều kiện trước khi add_action giúp tiết kiệm tài nguyên.

<?php
// Sai: luôn thêm hook
add_action('wp_head', 'custom_meta_tags');

// Đúng: chỉ frontend
if ( ! is_admin() && ! wp_doing_ajax() ) {
    add_action('wp_head', 'custom_meta_tags');
}

Checklist an toàn khi làm việc với Hook

  • Luôn đặt is_main_query() khi dùng pre_get_posts.
  • Không query database nặng trong the_content hoặc the_title.
  • Không thêm hook bên trong vòng lặp hoặc callback.
  • Remove filter/action nếu chỉ cần dùng tạm.
  • Chỉ thêm hook khi thực sự cần cho context hiện tại (frontend, admin, REST…).

Kết luận

Hook là công cụ mạnh mẽ, nhưng cũng dễ bị lạm dụng. Tránh các anti-pattern trên sẽ giúp code WordPress của bạn sạch hơn, dễ debug và nhanh hơn. Hãy xem lại plugin/theme bạn đang dùng, biết đâu chỉ cần vài chỉnh sửa hook là site đã cải thiện tốc độ rõ rệt.

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...