Hoàng Web

Thiết Kế Website WordPress

  • Kho giao diện
  • Dịch Vụ
    • Thiết kế web giá rẻ
    • Thiết kế website WordPress
    • Hosting Miễn Phí 100GB
    • Tích hợp thanh toán MoMo, ViettelPay, Vietcombank, MB..
    • Tối ưu Google PageSpeed
    • Sửa lỗi nâng cấp website
    • Viết plugin WordPress
    • Code Tool theo yêu cầu
  • Bảng giá
  • Quy trình làm việc
  • Giới thiệu
  • Liên Lạc
Trang chủ » Wordpress » Hướng dẫn tạo phân trang wordpress

Hướng dẫn tạo phân trang wordpress

Thứ Bảy, 12/07/2014 by Hoàng Quách

Nội dung

  • 1 Phân trang với $wpdb
  • 2 Phân trang trong trang tìm kiếm
    • 2.1 Chú ý:
  • 3 Phân trang sử dụng Plugin
      • 3.0.1 Tùy biến hiển thị nút phân trang
  • 4 Một số lỗi
    • 4.1 Lỗi 404
  • shares
  • Facebook
  • Facebook Messenger
  • Gmail
  • Viber
  • Skype

Phân trang trong wordpress là một tính năng giúp rút gọn thanh cuộn khi blog của bạn có từ 50-100 posts hoặc lên đến 1000 bài viết.
pagination wordpress

Phân trang xuất hiện ở trang category, home, archive. Thiết lập số lượng bài viết được show ra ở mỗi phân trang, bạn vào Settings ->Reading.
Thay đổi giá trị dòng Blog pages show at most, chỉ định lượng bài viết hiển thị/page. Nhấn Save changes để lưu lại option. Giá trị này được lấy bởi option:

echo get_option("posts_per_page");

Lấy thông tin số trang hiện tại xác định trên tham số URL.

$paged = 1;	//hoặc 0
if(get_query_var('paged')) {
  $paged = get_query_var('paged');
} elseif(get_query_var('page')) {
  $paged = get_query_var('page');
}

– Lấy dữ liệu trên phân trang hiện tại.

//sử dụng WP_Query
$posts_per_page=get_option("posts_per_page");  //posts per page
$big = 999999999;
$data=new WP_Query(
	array(
                ....
		'numberposts'=>-1,
		'posts_per_page'=>$posts_per_page,		
		'paged'=>$paged
                ....
	)
);
while($data->have_posts()):
$data->the_post();
...
endwhile;

– Hiển thị liên kết phân trang.

$big = 999999999;
echo paginate_links( array(
	'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),	
	
	'format' => '?paged=%#%',
	'current' => min($paged,1),	
	'total' =>$data->max_num_pages,
	'prev_text'=>'<<',
	'next_text'=>'>>',
	//thêm tham số vào liên kết phân trang.
	'add_args'=>array('abc'=>1)		//result: /page/2/?s=xx&abc=1
) );

Giải thích:

  • current: chỉ số trang hiện tại, luôn bắt đầu từ 1
  • total: tổng số trang được tìm thấy.
  • add_args: mảng tham số URL được thêm vào url phân trang.

Ngoài ra, có một số thông tin khác bạn cần biết như tổng số bài viết trong kết quả Query là $data->found_posts
Nếu sử dụng global $wp_query, thì biến instance của WP_Query chính là biến toàn cục $wp_query. Tương tự trả về số lượng bài viết được tìm thấy:

$wp_query->found_posts;

Với các template như category, home thì sẽ không sử dụng WP_Query, để can thiệp phân trang thì bạn dùng query_posts. Ví dụ:

global $wp_query, $querystring;

query_posts($querystring."&posts_per_page=10");

Có thể không cần chỉ định số trang vì mặc định có ‘posts_per_page’ trong main query. Và cần show liên kết phân trang như ở trên.

echo paginate_links( array(
	'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),	
	
	'format' => '?paged=%#%',
	'current' => min($paged,1),	
	'total' =>$wp_query->max_num_pages,
	'prev_text'=>'<<',
	'next_text'=>'>>',
	//thêm tham số vào liên kết phân trang.
	'add_args'=>array('abc'=>1)		//result: /page/2/?s=xx&abc=1
) );

WordPress có biến global của WP_Query là $wp_query, dùng biến này để biết tổng số trang được tìm thấy. Viết lại cấu trúc đường dẫn phân trang vào thuộc tính ‘base’ và ‘format’. Bạn có thể sử dụng định dạng này.

echo paginate_links( array(
     'base' => get_pagenum_link(1) . '%_%',  
     'format' => 'page/%#%/',
    ...
));

Nếu bạn muốn tạo danh sách authors có phân trang, thì với hàm get_users cũng có thể giúp bạn làm được điều đó nhưng sử dụng tham số ‘offset‘ thay vì ‘posts_per_page‘. Ngoài class WP_Query đây là một giải pháp được tích hợp sẵn, xem thêm tại đây.

Phân trang với $wpdb

Nếu website wordpress của bạn tạo thêm bảng và muốn phân trang cho dữ liệu được liệt kê trong bảng thì làm thế nào?
Bạn chỉ băn khoăn tìm công thức tính tổng số trang bạn muốn hiện thị phù hợp với kết quả trích xuất từ bảng đó.

Thật đơn giản sử dụng công thức sau:

//$total: tổng số bài viết (dòng) được tìm thấy
//$posts_per_page: số bài viết (dòng) /1 page
ceil($total / $posts_per_page);

Tham khảo ví dụ sau đây:

$data=$wpdb->get_results("select * from wp_mytable");
$page = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1;
$posts_per_page=3;  //posts per page
$total=count($data);	//total 100 rows
echo paginate_links( array(
    'base' => add_query_arg( 'cpage', '%#%' ),
    'format' => '',
    'current' => $page,
    'total' =>ceil($total / $posts_per_page),
    'prev_text'=>__('<<'),
    'next_text'=>__('>>')
) );

Đôi khi class WP_Query không thực hiện được câu lệnh SQL phức tạp, bạn phải viết chuỗi SQL trực tiếp vào $wpdb. Chúng ta sẽ sử dụng biến SQL_CALC_FOUND_ROWS để lấy tổng số records được tìm thấy, kết hợp với lệnh LIMIT giới hạn kết quả records thỏa mãn chuỗi lệnh SELECT.
Chép đoạn code sau trong functions.php

function pagination_wpdb( ){
    global $wpdb, $paged, $max_num_pages, $current_date;

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    $post_per_page = intval(get_query_var('posts_per_page'));
    $offset = ($paged - 1)*$post_per_page;

    /* Custom sql here. I left out the important bits and deleted the body 
     as it will be specific when you have your own. */
    $sql = "
        SELECT SQL_CALC_FOUND_ROWS  {$wpdb->posts}.*
        FROM {$wpdb->posts}
        ....
        GROUP BY {$wpdb->posts}.ID 
        ORDER BY {$wpdb->posts}.post_date DESC
        LIMIT ".$offset.", ".$post_per_page."; ";   

    $sql_result = $wpdb->get_results( $sql, OBJECT);

    /* Determine the total of results found to calculate the max_num_pages
     for next_posts_link navigation */
    $sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
    $max_num_pages = ceil($sql_posts_total / $post_per_page);

    return $sql_result;
}

Bạn nên kế thừa tham số phân trang ‘paged’ hoặc có thể lưu vào tham số khác. Nhưng việc sử dụng tham số ‘paged’ liên quan đến các hàm sử lý phân trang trong wordpress là điều tốt nhất. Truyền tổng số page $max_num_pages vào hàm hiển thị liên kết trang previous_posts_link và next_posts_link.

<?php 
    $pagination_sql = pagination_wpdb();
    /*followed by a standart loop to display your results */ 
    foreach($pagination_sql as $item){
	echo $item->post_title.'<br/>';
     }
 ?>
<div class="navigation">
    <div class="previous panel"><?php previous_posts_link('&laquo; previous',$max_num_pages) ?></div>
    <div class="next panel"><?php next_posts_link('next &raquo;',$max_num_pages) ?></div>
</div>

Kết quả giống như thế này:
pagination-wpdb

Bạn có thể liệt kê chỉ số trang bởi hàm paginate_links.

<?php
$big = 999999999;
echo paginate_links( array(
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),   
     
    'format' => '?paged=%#%',
    'current' => min($paged,1),  
    'total' =>$max_num_pages,
    'prev_text'=>'<<',
    'next_text'=>'>>',
) );
?>

Kết quả:
pagination-wpdb1

Phân trang trong trang tìm kiếm

Tạo phân trang trong trang tìm kiếm cũng giống như trên, có điều chú ý tới thuộc tính action của form.

<form method="get" action="<?php echo home_url('/')?>">

Thêm ký tự slash “/” sau url bởi hàm home_url('/') thì paginate_links mới hoạt động.

Chú ý:

Nếu số lượng bài viết cần lấy trong một phân trang nằm ngoài option “Blog pages show at most” trong phần Settings->reading hay chỉ định thuộc tính “posts_per_page”!=get_option(‘posts_per_page’) trong WP_Query, query_posts thì có hoạt động không?
Tất nhiên là hoạt động được, nhưng lưu ý giá trị posts_per_page >= (settings->reading->Blog pages show at most) không chênh nhau quá có thể chênh từ 1,2,3

Ví dụ: Giá tri trong settings->reading->Blog pages show at most đặt là 10 mà bạn muốn hiển thị 5 kết quả trong 1 phân trang thì phân trang sẽ không hoạt động.

Phân trang sử dụng Plugin

Cách đơn giản nhất và an toàn đối với những người không sành về code , là sử dụng plugin để làm việc phân trang này. Bạn có thể tải plugin “WP-PageNavi“.
Sau khi tải về giải nén vào thư mục plugins, rồi kích hoạt. Sau khi kích hoạt xong bạn cấu hình plugin để thay đổi một số hiển thị. Vào settings->PageNavi đừng quên nhấn Save Changes để lưu lại thay đổi.

*Cách Sử dụng:
Trong theme Twentyten bạn thấy có dòng phân trang:

<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">&larr;</span> Older posts', 'twentyten' ) ); ?></div>
<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">&rarr;</span>', 'twentyten' ) ); ?></div>

2 dòng trên có tác dụng next/prev bài viết. Với plugin WP-Pagenavi này giờ đây bạn chỉ thay bởi 1 dòng đơn giản sau:

<?php wp_pagenavi(); ?>

Tạo phân trang với custom queries.
Cách 1:

query_posts( array( 'tag' => 'foo', 'paged' => get_query_var('paged') ) );

while ( have_posts() ) : the_post();
	the_title();
	// more stuff here
endwhile;

wp_pagenavi();

wp_reset_query();	// avoid errors further down the page

Cách 2: sử dụng WP_Query, quản lý sẽ tốt hơn. Với cách này bạn cần khai báo đối tượng độc lập WP_Query vào hàm wp_reset_postdata

$my_query = new WP_Query( array( 'tag' => 'foo', 'paged' => get_query_var('paged') ) );

while ( $my_query->have_posts() ) : $my_query->the_post();
	the_title();
	// more stuff here
endwhile;

wp_pagenavi( array( 'query' => $my_query ) );

wp_reset_postdata();	// avoid errors further down the page

Xem chi tiết cách dùng: tại đây.

Tùy biến hiển thị nút phân trang

tùy biến hiển thị liên kết phân trang
Bạn có thể sử dụng hook để sửa lại mọi nội dung pagination tạo bởi wp_pagenavi. Ví dụ thêm đoạn code sau vào functions.php

//attach our function to the wp_pagenavi filter
add_filter( 'wp_pagenavi', 'ik_pagination', 10, 2 );
 
//customize the PageNavi HTML before it is output
function ik_pagination($html) {
	$out = '';
 
	//wrap a's and span's in li's
	$out = str_replace("<a","<li><a",$html);	
	$out = str_replace("</a>","</a></li>",$out);
	$out = str_replace("<span","<li><span",$out);	
	$out = str_replace("</span>","</span></li>",$out);
 
	return '<div class="paging">
			<ul>'.$out.'</ul>
		</div>';
}

Lưu ý: sử dụng str_replace thay tên class của thẻ liên kết, và thêm thẻ HTML nếu muốn, nhưng tránh dùng từ “page” vì nó sẽ thay thế URL /page/ làm hỏng liên kết sang trang tới và lui.

Một số lỗi

Lỗi 404

Khi nhảy đến trang 2 có báo lỗi 404 không tìm thấy, nếu gặp lỗi này bạn nên kiểm tra lại hook pre_get_posts.

*Chỉnh lại prep_get_posts:

function my_post_queries( $query ) {
    // do not alter the query on wp-admin pages and only alter it if it's the main query
    if ($query->is_main_query()){

        // alter the query for the home and category pages
        if(is_home()){
            //$query->set('posts_per_page', 5);
            if(!$query->get('post_type')){
                $query->set('post_type',array(tutorial_posttype,'post'));
            }
            
        }
	}
}

– Ví dụ vì nguyên nhân nào đó không xác định post_type thì bạn thiết lập lại post_type.
* Có thể thay thế page vs paged:

function remove_page_from_query_string($query_string)
{
    if (isset($query_string['name']) && $query_string['name'] == 'page' && isset($query_string['page'])) {
        unset($query_string['name']);
        // 'page' in the query_string looks like '/2', so i'm spliting it out
        list($delim, $page_index) = split('/', $query_string['page']);
        $query_string['paged'] = $page_index;
    }
    return $query_string;
}
// I will kill you if you remove this. I died two days for this line
add_filter('request', 'remove_page_from_query_string');

Hoặc thêm dòng sau:

function bti_change_posts_per_page(){ return 1; }
if( preg_match("|\/".get_option('tag_base')."\/.+\/page\/[0-9]+$|i", $_SERVER['REQUEST_URI']) ){
    add_filter( 'pre_option_posts_per_page' , 'bti_change_posts_per_page');
}

Tác giả: HOANGWEB.COM

Để nhận được bài viết mới vui lòng đăng ký kênh kiến thức WordPress từ A-Z ở Form bên dưới. Bạn cũng có thể nhận được sự trợ giúp trên Twitter và Facebook

  • shares
  • Facebook
  • Facebook Messenger
  • Gmail
  • Viber
  • Skype

Chuyên mục: Wordpress Tìm kiếm: pagination, wordpress Templates

Comments

  1. Cường says

    Thứ Tư, 10/09/2014 at 2:32 chiều

    Cái này mình mới up, chưa có nhiều tính năng lắm, sẽ bổ sung vào các phiên bản sau, mọi người dùng thử nhé:

    http://wordpress.org/plugins/sb-paginate/

  2. Cuong Pham says

    Thứ Ba, 19/03/2019 at 10:16 sáng

    Hi chào bạn.!!
    Mình có sử dụng code của bạn,nó hoạt động trên localhost nhưng khi mình up lên server thì báo lỗi Page not found, mình dùng với post

    • Lại Đình Cường says

      Thứ Ba, 19/03/2019 at 10:16 sáng

      Lỗi 404 là do bạn chưa cập nhật lại rewrite rules, bạn vào bảng điều khiển rồi vào Settings >> Permalinks nhé.

  3. CutieP says

    Thứ Tư, 20/03/2019 at 10:16 sáng

    Nó chỉ scroll được khi page đang load, load xong là không được nữa … 🙁

  4. hong tran says

    Thứ Tư, 20/03/2019 at 10:16 sáng

    perfect
    nhưng nếu muốn dạng thế này 1 2 3 …10 thì thế nào bác, hic

    • Lại Đình Cường says

      Thứ Hai, 18/03/2019 at 10:16 sáng

      Cái đó tùy thuộc vào bạn kiểm tra điều kiện trong vòng lặp. Bạn muốn ẩn từ page thứ mấy thì để … chỗ này.

  5. CutieP says

    Thứ Năm, 21/03/2019 at 10:16 sáng

    Chào bạn, cho mình hỏi là blog mình bị lỗi không dùng được scrollbar nhấn phím mũi tên để kéo trang lên xuống ấy. Mình cũng thử deactivate từng plugin mà vẫn không được, bạn biết cách chỉ mình với… Thanks bạn!!

    • Trung Hiếu says

      Chủ Nhật, 17/03/2019 at 10:16 sáng

      Site của bạn có sử dụng plugin nào để tối ưu hay cache JavaScript không? 😛

  6. Nguyễn Đỗ Nguyên says

    Thứ Năm, 18/06/2020 at 4:06 chiều

    a ơi e bị lỗi 404, mấy cái file a nói là nằm ở đây vậy ạ??!

Tôi giúp gì cho bạn?

HOÀNG WEB

Địa chỉ: Tây Sơn, Phường Quang Trung, Quận Đống Đa, Hà Nội

Hotline: 0987 342 124 – 0868 292 303 (8h:00 – 21h:00)

Email: [email protected]

Website: www.hoangweb.com

KẾT NỐI VỚI TÔI

  • Facebook
  • GitHub
  • YouTube

SẢN PHẨM

  • Plugin Thanh Toán Quét Mã QR Code Tự Động
  • WP2Speed – Tối ưu Google Speed
  • 23WebHost – Hosting Miễn Phí 100GB

LIÊN KẾT

  • Có nên thuê thiết kế website giá rẻ?
  • Hướng dẫn thanh toán
  • Chính sách hoàn tiền
  • Trung tâm hỗ trợ

Copyright © 2023 | All rights reserved | HOANG WEB
Mọi hình thức sao chép nội dung trên website này mà chưa được sự đồng ý đều là trái phép.