Nội dung
- shares
- 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.
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('« previous',$max_num_pages) ?></div> <div class="next panel"><?php next_posts_link('next »',$max_num_pages) ?></div> </div>
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'=>'>>', ) ); ?>
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">←</span> Older posts', 'twentyten' ) ); ?></div>
<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">→</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
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 Messenger
- Gmail
- Viber
- Skype
Cường says
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/
Cuong Pham says
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
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é.
CutieP says
Nó chỉ scroll được khi page đang load, load xong là không được nữa … 🙁
hong tran says
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
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.
CutieP says
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
Site của bạn có sử dụng plugin nào để tối ưu hay cache JavaScript không? 😛
Nguyễn Đỗ Nguyên says
a ơi e bị lỗi 404, mấy cái file a nói là nằm ở đây vậy ạ??!