Bài viết này mình chia sẻ đến bạn đoạn code có thể cải thiện tính năng tìm kiếm trên theme GeneratePress rất đáng kể. Mình trước đây có dùng plugin để tìm kiếm tiện lợi hơn, tuy nhiên phương án đó hơi nặng. Sau này làm lại blog thì mình không sử dụng plugin đó nữa, mà thêm code bên dưới vào theme để tính năng tìm kiếm ngon lành, chuẩn chỉnh hơn so với mặc định của WordPress.

Mình không hiểu tại sao tính năng tìm kiếm mặc định của WordPress lại tệ như vậy, bao nhiêu năm rồi mà giống kiểu làm cho có. Kết quả hiển thị rất là ho lao luôn, bài đúng ra phải hiển thị lên đầu kết quả tìm kiếm thì nó xếp ở tận đâu đâu. Nói chung bạn dùng code của mình bên dưới và so sánh với tính năng tìm kiếm mặc định sẽ thấy sự khác biệt rõ rệt ^^
Nói sơ qua về hướng của mình: Kết quả sẽ ưu tiên xếp bài viết có chứa nhiều khoá nhiều nhất thì lên đầu, số lần từ khoá xuất hiện càng ít thì đẩy xuống dưới, đồng thời hiển thị số lần từ khoá xuất hiện ở mỗi kết quả để người dùng nhìn thấy. Để sử dụng code này thì bạn copy và dán vào cuối file functions.php của theme/ child theme đang sử dụng là được.
//CẢI THIỆN TÌM KIẾM MẶC ĐỊNH THEME GENERATEPRESS
add_action('pre_get_posts',function($query){
if(is_admin()||!$query->is_main_query()||!$query->is_search())return;
$query->set('post_type','post');
$query->set('post_status','publish');
},1);
add_filter('posts_search',function($search,$wp_query){
if(is_admin()||!$wp_query->is_main_query()||!$wp_query->is_search())return $search;
global $wpdb;
$s=$wp_query->get('s');
if(empty($s))return $search;
$s_clean=hocban_vn_remove_accents($s);
$search_term='%'.$wpdb->esc_like($s).'%';
$search_term_clean='%'.$wpdb->esc_like($s_clean).'%';
$search=$wpdb->prepare(" AND ({$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_content LIKE %s OR {$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_content LIKE %s) ",$search_term,$search_term,$search_term_clean,$search_term_clean);
return $search;
},20,2);
add_filter('the_posts',function($posts,$wp_query){
if(is_admin()||!$wp_query->is_main_query()||!$wp_query->is_search()||empty($posts))return $posts;
$s=mb_strtolower(get_search_query(false),'UTF-8');
$s_clean=hocban_vn_remove_accents($s);
foreach($posts as $post){
$clean_title=hocban_vn_remove_accents(mb_strtolower($post->post_title,'UTF-8'));
$clean_content=hocban_vn_remove_accents(mb_strtolower(wp_strip_all_tags($post->post_content),'UTF-8'));
$count_title=mb_substr_count($clean_title,$s_clean,'UTF-8');
$count_content=mb_substr_count($clean_content,$s_clean,'UTF-8');
$post->hocban_score=($count_title*5)+$count_content;
}
usort($posts,function($a,$b){
if($b->hocban_score===$a->hocban_score){
return strtotime($b->post_date)-strtotime($a->post_date);
}
return $b->hocban_score-$a->hocban_score;
});
return $posts;
},20,2);
function hocban_vn_remove_accents($str){
if(empty($str))return '';
$dict=['a'=>['à','á','ả','ã','ạ','â','ầ','ấ','ẩ','ẫ','ậ','ă','ằ','ắ','ẳ','ẵ','ặ'],'e'=>['è','é','ẻ','ẽ','ẹ','ê','ề','ế','ể','ễ','ệ'],'i'=>['ì','í','ỉ','ĩ','ị'],'o'=>['ò','ó','ỏ','õ','ọ','ô','ồ','ố','ổ','ỗ','ộ','ơ','ờ','ớ','ở','ỡ','ợ'],'u'=>['ù','ú','ủ','ũ','ụ','ư','ừ','ứ','ử','ữ','ự'],'y'=>['ỳ','ý','ỷ','ỹ','ỵ'],'d'=>['đ']];
foreach($dict as $ascii=>$uni){$str=str_replace($uni,$ascii,$str);}
return $str;
}
function hocban_display_keyword_count():void{
if(!is_search()||!in_the_loop()||!is_main_query())return;
$s=trim((string)get_search_query(false));
if($s==='')return;
global $post;
$text_clean=hocban_vn_remove_accents(mb_strtolower($post->post_title.' '.wp_strip_all_tags($post->post_content),'UTF-8'));
$s_clean=hocban_vn_remove_accents(mb_strtolower($s,'UTF-8'));
$count=mb_substr_count($text_clean,$s_clean,'UTF-8');
if($count>0){
printf('<p class="hocban-search-count">Từ khóa <span class="hocban-highlight">%s</span> xuất hiện <strong>%s</strong> lần</p>',esc_html($s),number_format_i18n($count));
}
}
add_action('generate_after_entry_title','hocban_display_keyword_count');
add_action('wp_enqueue_scripts',function():void{
if(!is_search())return;
$css='.hocban-search-count{margin:12px 0 18px;font-size:15px;color:#222;font-weight:500;line-height:1.5;}.hocban-highlight{background:#fff000;color:#000;padding:3px 10px;border-radius:6px;font-weight:900;box-shadow:0 2px 6px rgba(0,0,0,0.25);display:inline-block;}.hocban-search-count strong{color:#d00;font-size:18px;font-weight:900;}';
wp_add_inline_style('generate-style',$css);
},99);
//HẾT CODE CẢI THIỆN TÌM KIẾM MẶC ĐỊNHNgoài ra, theo góp ý của bạn Bùi Trung Hiếu (WP Căn Bản), mình đã xử lý lại vấn đề hiệu suất, giúp tránh quá tải khi nội dung web quá nhiều. Các bác coder/ dev xem qua, có gì góp ý thêm giúp em các vấn đề về SEO, hiệu suất, bảo mật với ạ !
Cả 2 code bên trên đều gặp vấn đề lớn về mặt hiệu năng bác Tịnh nhé. Kết luận nhanh:
– Code 1: rất tốn CPU khi có nhiều bài hoặc bài có nội dung dài. Tệ nhất là ORDER BY tính score bằng string functions.
– Code 2: nặng toàn diện (truy vấn DB toàn bộ bài viết + xử lý bằng PHP thay vì MySQL + sort). Với site nhỏ vài trăm bài đổ thì “có vẻ ổn”. Với site lớn một chút thì đây là kiểu search dễ làm crash hoặc timeout do tràn RAM và full CPU.
Bác nên kiểm tra lại. Do bình luận của bác giới hạn số lượng chữ nên em không viết cụ thể được. 😂
Uầy hay ta, cảm ơn bạn Hiếu nhé, có gì nhờ bạn góp ý thêm. Mình cập nhật lại code rồi nè, giờ oke rồi á ^^
Cái này dùng cho flatsome được không bác?
Test thử bác, cái này e làm riêng cho GeneratePress, nhưng có thể dựa vào đó để dùng AI ráp vào Flatsome/ theme khác á bác. Bác copy code đưa cho Gemini, Grok, Claude, Chat GPT nó chỉnh lại cho ^^