程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> 使用PHP+AJAX讓WordPress動態加載文章的教程

使用PHP+AJAX讓WordPress動態加載文章的教程

編輯:PHP綜合

為什麼要動態加載文章?

1. 快速向訪客展示頁面
文章很容是包含大量文字和多媒體資源 (如: 圖片, 視頻, 音樂), 加載這些內容需要占用很多的時間. 如果你的頁面上存在大量文章, 當訪客發現頁面久久沒有加載完成就感到不耐煩. 這是動態加載文章的主要目的.

2. 讓文章列表化
使頁面上的文章成為一個列表, 減少頁面的空間占用, 訪客可以方便的移動到頁面下方, 提高舊文章被點擊的幾率. 並且你可以在頁面上放置更多的文章而不用擔心頁面過長.

為什麼不動態加載文章?

1. 對搜索引擎不友好
搜索引擎優化的目的是將有價值的東西盡量多的向搜索爬蟲展示, 包括最新的文章內容. 只有標題的文章讓爬蟲只知道這個文章而不知其文章側重, 使用 JavaScript 輸出的文章內容未必可以被抓取和分析. 這些對 SEO 來說都是不好的.
後來發現, 如果你的網站有固定的文章類型, 沒有畢業在文章列表頁顯示太多文章內容, 表示影響不大.

2. 增加了請求次數
雖然將文章折疊起來, 我們一般還是會想辦法向訪客顯示前面的幾篇文章. 這樣對用戶是友好的, 但是要增加請求的次數和數據庫訪問的次數.
後來我有選擇地顯示部分文章內容, 而且不是通過異步加載的方式, 也就是說, 這個問題是可以通過簡單的修改解決掉的.

3. 一些插件失效
因為需要自定義方法抓取文章, 如果不添加特殊處理, 很可能令部分 WordPress 插件失效.
可以通過特殊處理解決掉, 以後文章中會提及.

動態加載文章的設計思路

1. 找到頁面上所有文章
為每個文章添加一個展開/折疊按鈕

2. 向文章添加展開/折疊按鈕
點擊按鈕, 如果文章內容沒有加載, 加載並展開文章內容.
點擊按鈕, 如果文章內容已經加載, 則展開/折疊文章內容.

3. 加載文章內容
將文章的 id 發往後台, 在數據庫中找到相應的文章內容並進行格式化, 返回響應顯示在頁面上.

JavaScript 處理代碼分析

1. 找到頁面上所有文章

/ 在文檔加載完畢的時候遍歷所有匹配文章的元素
jQuery(document).ready(function(){
 jQuery('div.post').each(function() {
 // 如果元素相應位置是文章 ID
 var id = jQuery(this).attr('id');
 if(/^post\-[0-9]+$/.test(id)) {
  // 則為每個文章添加一個展開/折疊按鈕
  ...
 }
 });
});

2. 向文章添加展開/折疊按鈕
toggle.toggle(function() { // 展開
 // 如果文章內容為空, 加載文章內容
 if(jQuery('#' + id + ' .content').text() == '') {
 ...
 }
 // 顯示文章內容, 並切換按鈕樣式
 jQuery('#' + id + ' .content').slideDown();
 jQuery(this).removeClass('collapse').addClass('expand');
},
function() { // 折疊
 // 隱藏文章內容, 並切換按鈕樣式
 jQuery('#' + id + ' .content').slideUp();
 jQuery(this).removeClass('expand').addClass('collapse');
// 將按鈕追加到文章標題前方
}).prependTo(jQuery('#' + id + ' h2'));

3. 加載文章內容

// 取得文章 ID
var postId = id.slice(5);
// 使用 AJAX 獲取並處理文章內容
jQuery.ajax({
 type:     'GET'
 ,url:     '?action=load_post&id=' + postId
 ,cache:    false
 ,dataType:  'html'
 ,contentType: 'application/json; charset=utf-8'
 // 取得返回內容之前顯示加載信息
 ,beforeSend: function(data){loadPostContent(id, '<p class="ajax-loader">Loading...</p>');}
 // 獲取文章內容成功, 更新文章內容
 ,success:   function(data){loadPostContent(id, data);}
 // 獲取文章內容失敗, 顯示出錯提示
 ,error:    function(data){loadPostContent(id, '<p>Oops, failed to load data.</p>');}
});

後台處理
處理思路

從前台傳到後台的參數有兩個, 一個是 action ID, 用於確定使用的接口, 另一個是文章的 ID, 用於獲取文章對應的內容.

下面我們來分析一下wp-includes/post-template.php 的 get_the_content 方法.

function get_the_content($more_link_text = null, $stripteaser = 0) {
 global $id, $post, $more, $page, $pages, $multipage, $preview;
 
 // 設定 "查看全文" 的鏈接文案
 if ( null === $more_link_text )
 $more_link_text = __( '(more...)' );
 
 // 返回內容
 $output = '';
 
 // More 標簽是否存在的標記位
 $hasTeaser = false;
 
 // 如果文章要求輸入密碼, 並且在 Cookie 中找不到處理過的信息, 則返回要求輸入密碼的查看表單
 if ( post_password_required($post) ) {
 $output = get_the_password_form();
 return $output;
 }
 
 // 請求的文章片段對應的頁面大於最大頁數 (即文章片段不存在), 則返回最大頁碼的文章片段
 if ( $page > count($pages) )
 $page = count($pages);
 
 // 文章內容是最後分頁中的文章片段
 $content = $pages[$page-1];
 // 如果文中有 More 標簽, 要求切斷文章並輸出 "查看全文" 鏈接, 則重定義文章內容, 標記 More 標簽存在
 if ( preg_match('/<!--more(.*?)?-->/', $content, $matches) ) {
 $content = explode($matches[0], $content, 2);
 if ( !empty($matches[1]) && !empty($more_link_text) )
  $more_link_text = strip_tags(wp_kses_no_null(trim($matches[1])));
 
 $hasTeaser = true;
 } else {
 $content = array($content);
 }
 
 // 如果進行了文章切斷處理, 且不存在分頁要求, 
 if ( (false !== strpos($post->post_content, '<!-- noteaser -->') && ((!$multipage) || ($page==1))) )
 $stripteaser = 1;
 
 // 獲取文章內容的第一部分; 如果在獨立文章存在 Read more 和切斷處理, 則文章內容為空
 $teaser = $content[0];
 if ( ($more) && ($stripteaser) && ($hasTeaser) )
 $teaser = '';
 $output .= $teaser;
 
 // 如果文章分為多個片段, 在獨立文章中拼接上第二部分, 摘要內容中顯示 "閱讀全文" 鏈接
 if ( count($content) > 1 ) {
 if ( $more ) {
  $output .= '<span id="more-' . $id . '"></span>' . $content[1];
 } else {
  if ( ! empty($more_link_text) )
  $output .= apply_filters( 'the_content_more_link', ' <a href="' . get_permalink() . "#more-$id\" class=\"more-link\">$more_link_text</a>", $more_link_text );
  $output = force_balance_tags($output);
 }
 
 }
 
 if ( $preview ) // preview fix for javascript bug with foreign languages
 $output = preg_replace_callback('/\%u([0-9A-F]{4})/', create_function('$match', 'return "&#" . base_convert($match[1], 16, 10) . ";";'), $output);
 
 // 返回文章內容
 return $preview;
}

你完全可以這樣想: 只要滿足一些傳入的參數, 去除一些不必要的, 更換一些可取代的, 將頁面返回改成輸出, 就是一個輸出文章內容的接口.

處理方法

如果我們暫時不考慮輸入密碼, 分頁等功能; 另外, 因為 More 和切斷功能不應該在展開文章內容中存在, 響應處理可以變得很簡單. 我們要做的事就這麼幾個:
1. 做出 action 對應的接口
2. 獲取指定文章的內容
3. 格式化文章內容
4. 返回文章內容

多說無用, 直接上代碼, 加注釋:

function load_post() {
 // 如果 action ID 是 load_post, 並且傳入的必須參數存在, 則執行響應方法
 if($_GET['action'] == 'load_post' && $_GET['id'] != '') {
 $id = $_GET["id"];
 $output = '';
 
 // 獲取文章對象
 global $wpdb, $post;
 $post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $id));
 
 // 如果指定 ID 的文章存在, 則對他進行格式化
 if($post) {
  $content = $post->post_content;
  $output = balanceTags($content);
  $output = wpautop($output);
 }
 
 // 打印文章內容並中斷後面的處理
 echo $output;
 die();
 }
}
// 將接口加到 init 中
add_action('init', 'load_post');

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved