Dưới đây là hàm PHP trong WordPress để lấy tất cả các bài viết cùng chuyên mục (category) và cùng thẻ (post_tag) với bài viết hiện tại:

function get_related_posts_by_category_and_tag($post_id, $limit = 5) {
    // Lấy ID của các chuyên mục (categories) của bài viết hiện tại
    $categories = wp_get_post_categories($post_id);
    // Lấy ID của các thẻ (tags) của bài viết hiện tại
    $tags = wp_get_post_tags($post_id, array('fields' => 'ids'));

    // Khởi tạo mảng kết quả
    $results = array();

    // Tạo một mảng điều kiện cho WP_Query
    $args = array(
        'post__not_in' => array($post_id), // Loại trừ bài viết hiện tại
        'posts_per_page' => $limit, // Giới hạn số lượng bài viết lấy ra
        'ignore_sticky_posts' => 1, // Bỏ qua các bài viết ghim
        'category__in' => $categories, // Lấy các bài viết cùng chuyên mục
        'tag__in' => $tags, // Lấy các bài viết cùng thẻ
        'post_type' => 'post', // Chỉ lấy các bài viết
        'post_status' => 'publish', // Chỉ lấy các bài viết đã xuất bản
    );

    // Thực thi truy vấn
    $related_posts = new WP_Query($args);

    // Nếu có bài viết liên quan, thêm vào mảng kết quả
    if ($related_posts->have_posts()) {
        while ($related_posts->have_posts()) {
            $related_posts->the_post();
            $results[] = array(
                'ID' => get_the_ID(),
                'title' => get_the_title(),
                'permalink' => get_permalink(),
                'excerpt' => get_the_excerpt(),
                'thumbnail' => get_the_post_thumbnail_url(get_the_ID(), 'thumbnail')
            );
        }
    }

    // Reset lại truy vấn
    wp_reset_postdata();

    // Nếu số lượng bài viết liên quan không đủ, lấy thêm từ các chuyên mục cha
    if (count($results) < $limit) {
        // Lấy ID của các chuyên mục cha
        $parent_categories = array();
        foreach ($categories as $category_id) {
            $parent = get_category($category_id)->parent;
            if ($parent && !in_array($parent, $parent_categories)) {
                $parent_categories[] = $parent;
            }
        }

        // Nếu có chuyên mục cha, tiếp tục truy vấn
        if (!empty($parent_categories)) {
            $remaining_posts = $limit - count($results);
            $args['posts_per_page'] = $remaining_posts;
            $args['category__in'] = $parent_categories;
            unset($args['tag__in']); // Bỏ điều kiện thẻ để mở rộng kết quả

            // Thực thi truy vấn lần thứ hai
            $parent_related_posts = new WP_Query($args);

            if ($parent_related_posts->have_posts()) {
                while ($parent_related_posts->have_posts()) {
                    $parent_related_posts->the_post();
                    $results[] = array(
                        'ID' => get_the_ID(),
                        'title' => get_the_title(),
                        'permalink' => get_permalink(),
                        'excerpt' => get_the_excerpt(),
                        'thumbnail' => get_the_post_thumbnail_url(get_the_ID(), 'thumbnail')
                    );
                }
            }

            // Reset lại truy vấn
            wp_reset_postdata();
        }
    }

    // Trả về mảng kết quả
    return $results;
}

Giải thích:

  1. wp_get_post_categories($post_id): Lấy danh sách ID của các chuyên mục mà bài viết hiện tại thuộc về.
  2. wp_get_post_tags($post_id, array('fields' => 'ids')): Lấy danh sách ID của các thẻ mà bài viết hiện tại sử dụng.
  3. WP_Query: Dùng để truy vấn các bài viết khác dựa trên chuyên mục và thẻ tương ứng.
  4. post__not_in: Loại trừ bài viết hiện tại khỏi kết quả để tránh hiển thị lại chính bài viết đó.
  5. posts_per_page: Giới hạn số lượng bài viết liên quan được hiển thị.
  6. Duyệt qua danh sách chuyên mục của bài viết hiện tại để lấy ID của chuyên mục cha.Tiến hành truy vấn các bài viết từ chuyên mục cha, không cần điều kiện thẻ để mở rộng phạm vi kết quả.Truy vấn này cũng loại trừ bài viết hiện tại và lấy thêm số bài viết còn thiếu.

Tùy chỉnh:

  • Bạn có thể thay đổi tham số $limit để điều chỉnh số lượng bài viết liên quan được hiển thị.
  • Nếu bạn muốn lấy thêm thông tin như hình ảnh đại diện (thumbnail) hoặc đoạn trích (excerpt), bạn có thể chỉnh sửa thêm trong vòng lặp while.

Hàm này sẽ giúp bạn dễ dàng lấy các bài viết liên quan dựa trên cả chuyên mục và thẻ trong WordPress, và có thể tùy chỉnh theo nhu cầu của bạn.

Cách sử dụng hàm:

Bạn có thể sử dụng hàm này trong template của WordPress để lấy dữ liệu và hiển thị chúng theo nhu cầu của bạn:

<?php
// Gọi hàm và lấy mảng dữ liệu bài viết liên quan
$related_posts = get_related_posts_by_category_and_tag(get_the_ID());

if (!empty($related_posts)) {
    echo '<ul>';
    foreach ($related_posts as $post) {
        echo '<li>';
        echo '<a href="' . esc_url($post['permalink']) . '">' . esc_html($post['title']) . '</a>';
        echo '<p>' . esc_html($post['excerpt']) . '</p>';
        if ($post['thumbnail']) {
            echo '<img src="' . esc_url($post['thumbnail']) . '" alt="' . esc_attr($post['title']) . '">';
        }
        echo '</li>';
    }
    echo '</ul>';
} else {
    echo 'Không có bài viết liên quan.';
}
?>

Tùy chỉnh:

  • Bạn có thể thay đổi thông tin trả về trong mảng, chẳng hạn thêm date, author, hoặc bất kỳ thông tin nào khác mà bạn muốn hiển thị.
  • Sử dụng hàm esc_url()esc_html() để đảm bảo dữ liệu được thoát (escape) an toàn khi hiển thị.

Với hàm này, bạn có thể linh hoạt lấy và xử lý các bài viết liên quan dựa trên chuyên mục và thẻ, trả về dưới dạng mảng để dễ dàng sử dụng trong các phần khác của trang web.