Dưới đây là một hàm phân trang nhẹ – đẹp – hoạt động tốt với mọi trang (bao gồm cả blog chính, category, custom query, custom post type archive…).
Mã nguồn hàm init_pagination()
Mình xuất phân trang của UIkit, bạn có thể tùy chỉnh lại cho phù hợp với dự án của mình nhé.
function init_pagination($query = null) {
$paged = max(1, get_query_var('paged'));
// Nếu không truyền gì → dùng global $wp_query
if (is_null($query)) {
global $wp_query;
$query = $wp_query;
}
// Nếu truyền số nguyên thì tạo đối tượng giả
if (is_numeric($query)) {
$pages = (int) $query;
} elseif ($query instanceof WP_Query) {
$pages = $query->max_num_pages;
} else {
$pages = 1;
}
if ($pages <= 1) return;
echo '<nav class="uk-margin-medium-top" aria-label="Pagination"><ul class="uk-pagination uk-flex-center">';
// Nút "Trước"
$prev_class = ($paged == 1) ? 'uk-disabled' : '';
$prev_link = ($paged > 1) ? get_pagenum_link($paged - 1) : '#';
echo '<li id="prev-link" class="'.$prev_class.'"><a href="'.$prev_link.'"><span class="uk-margin-small-right" uk-pagination-previous></span></a></li>';
// Các số trang
$range = 2;
$show_ellipsis = false;
for ($i = 1; $i <= $pages; $i++) {
if ($i == 1 || $i == $pages || ($i >= $paged - $range && $i <= $paged + $range)) {
$active = ($i == $paged) ? ' class="uk-active"' : '';
echo '<li'.$active.'><a href="' . get_pagenum_link($i) . '">' . $i . '</a></li>';
$show_ellipsis = true;
} else {
if ($show_ellipsis) {
echo '<li class="uk-disabled"><span>…</span></li>';
$show_ellipsis = false;
}
}
}
// Nút "Sau"
$next_class = ($paged == $pages) ? 'uk-disabled' : '';
$next_link = ($paged < $pages) ? get_pagenum_link($paged + 1) : '#';
echo '<li id="next-link" class="'.$next_class.'"><a href="'.$next_link.'"><span class="uk-margin-small-left" uk-pagination-next></span></a></li>';
echo '</ul></nav>';
}
Ưu điểm nổi bật
- Tự động nhận
pagedvà URL phân trang từ hệ thống WordPress. - Dùng được với mọi truy vấn:
WP_Query,pre_get_posts, hoặc truy vấn archive mặc định. - Hiện dấu
…khi cần, giúp gọn gàng với số trang lớn. - Giao diện HTML dễ tùy chỉnh: có thể thay đổi thành Bootstrap, Tailwind, hoặc bất kỳ framework nào.
- Không phụ thuộc plugin, siêu nhẹ và tối ưu.
Phiên bản hàm init_pagination() dùng paginate_links()
function init_pagination_links($query = null) {
$paged = max(1, get_query_var('paged'));
// Dùng global $wp_query nếu không truyền gì
if (is_null($query)) {
global $wp_query;
$query = $wp_query;
}
// Lấy tổng số trang
$total_pages = ($query instanceof WP_Query) ? $query->max_num_pages : (int) $query;
if ($total_pages <= 1) return;
$args = [
'base' => str_replace(999999999, '%#%', esc_url(get_pagenum_link(999999999))),
'format' => '?paged=%#%',
'current' => $paged,
'total' => $total_pages,
'prev_text' => '<span class="uk-margin-small-right" uk-pagination-previous></span>',
'next_text' => '<span class="uk-margin-small-left" uk-pagination-next></span>',
'type' => 'array'
];
$links = paginate_links($args);
if (!empty($links)) {
echo '<nav class="uk-margin-medium-top" aria-label="Pagination"><ul class="uk-pagination uk-flex-center">';
foreach ($links as $link) {
$is_active = strpos($link, 'current') !== false ? ' class="uk-active"' : '';
$is_disabled = strpos($link, 'next') !== false && $paged >= $total_pages || strpos($link, 'prev') !== false && $paged <= 1;
$disabled_class = $is_disabled ? ' class="uk-disabled"' : '';
// Gắn class chính xác theo UIKit
echo '<li' . $is_active . $disabled_class . '>' . $link . '</li>';
}
echo '</ul></nav>';
}
}
Ưu điểm của phiên bản này
- Chuẩn WordPress: Dùng
paginate_links()nên dễ dàng mở rộng, tương thích plugin SEO và caching. - Tùy biến dễ: Thêm
format,base,prev_text,next_textđể phù hợp mọi cấu trúc permalink. - Kết quả trả về dạng mảng (
type => 'array') → dễ wrap trong HTML tuỳ thích.
Lưu ý
- Nếu bạn dùng
format => '?paged=%#%', đảm bảo Permalink dạng mặc định. Nếu bạn dùng permalink đẹp (/%postname%/), WordPress sẽ tự xử lý. - Hàm
get_pagenum_link()đã tự tính toánbasetốt rồi, nhưng vẫn nên dùngstr_replace()như ví dụ để đảm bảo tính ổn định.
Cách sử dụng
Trong trang archive:
if (have_posts()) {
while (have_posts()) {
the_post();
// hiển thị bài viết
}
// Phân trang
init_pagination(); // dùng global $wp_query
}
Hoặc nếu bạn dùng WP_Query:
$args = [
'post_type' => 'post',
'paged' => get_query_var('paged') ?: 1,
'posts_per_page' => 10,
];
$my_query = new WP_Query($args);
if ($my_query->have_posts()) {
while ($my_query->have_posts()) {
$my_query->the_post();
// hiển thị
}
// Phân trang
init_pagination($my_query);
wp_reset_postdata();
}
Kết luận
Với init_pagination(), bạn có thể dễ dàng thêm phân trang đẹp, đúng chuẩn, và hiệu suất cao vào bất kỳ theme nào. Hàm này giúp bạn thoải mái kiểm soát giao diện, tránh việc phải phụ thuộc vào plugin hoặc code thừa của theme bên thứ ba.
Bình luận